Created
October 22, 2019 17:56
-
-
Save guru-florida/378076f154c10c6d171608c1e82b2e3c to your computer and use it in GitHub Desktop.
Smooth Timeline control in Vega
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"$schema": "https://vega.github.io/schema/vega/v5.json", | |
"width": 1500, | |
"height": 50, | |
"padding": 15, | |
"signals": [ | |
{ | |
"name": "rangeLimits", | |
"value": [30, 120] | |
}, | |
{ | |
"name": "scrollock", | |
"value": false, | |
"on": [{ | |
"events": "window:keyup![!event.shiftKey && !event.ctrlKey && event.keyCode==76]", | |
"update": "!scrollock" | |
}] | |
}, | |
{ | |
"name": "tsvelocity", "value": 0, | |
"description": "current velocity of the timeline (ex. throwing the timeline)", | |
"on": [{ | |
"events": { | |
"type": "timer", | |
"throttle": 100 | |
}, | |
"update": "abs(tsvelocity) > 60000 ? tsvelocity * tsacc : 0" | |
}, { | |
"events": "mousemove[event.buttons]", | |
"update": "scrollock ? 0 :-event.movementX * 400000" | |
}] | |
}, { | |
"name": "tsacc", "value": 0.75, | |
"description": "deaccelleration parameter controls how quickly the the timeline stops after a throw" | |
}, | |
{ | |
"name": "tsrange", "value": 120, | |
"description": "zoom setting, larger values means we are zooming out on the timeline", | |
"on": [{ | |
"events": "wheel", | |
"update": "clamp(tsrange + (event.deltaY * 5), rangeLimits[0], rangeLimits[1])" | |
}] | |
}, | |
{ | |
"name": "tspick", "value": 0, | |
"on":[{ | |
"events": "mousedown", | |
"update": "floor(invert('lin_timescale', clamp(x(), 0, width)))" | |
}, { | |
"events": "mouseup", | |
"update": "0" | |
}] | |
}, | |
{ | |
"name": "centerts", "value": 1568164000000, | |
"description": "timestamp that represents the center, the range is then extended to the left and right", | |
"on": [{ | |
"events": "mousemove[event.buttons]", | |
"update": "(tspick===0 || scrollock) ? centerts : centerts + (tspick - invert('lin_timescale', clamp(x(), 0, width)))" | |
}, { | |
"events": { | |
"type": "timer", | |
"throttle": 33 | |
}, | |
"update": "(tspick > 0) ? centerts : floor(centerts + tsvelocity/33)" | |
}, { | |
"events": "window:keyup![!event.shiftKey && (event.keyCode>48) && (event.keyCode<59) ]", | |
"update": "warn('goto ', (isDefined(data('bookmarks')[event.keyCode - 49]) && data('bookmarks')[event.keyCode - 49].ts) ? data('bookmarks')[event.keyCode - 49].ts : centerts)" | |
}, { | |
"events": "window:keyup![event.shiftKey && event.keyCode==37]", | |
"update": "centerts - 86400000" | |
}, { | |
"events": "window:keyup![event.shiftKey && event.keyCode==39]", | |
"update": "centerts + 86400000" | |
}, { | |
"events": "window:keyup![!event.shiftKey && event.keyCode==37]", | |
"update": "centerts - 3600000" | |
}, { | |
"events": "window:keyup![!event.shiftKey && event.keyCode==39]", | |
"update": "centerts + 3600000" | |
},{ | |
"events": "window:keyup![!event.shiftKey && event.keyCode==78]", | |
"update": "1569797913000" | |
},{ | |
"events": "mousedown", | |
"update": "(datum && datum.shortcut && datum.ts) ? datum.ts : centerts" | |
}] | |
}, | |
{ | |
"name": "startts", "value": 1568152000000, "update": "centerts - (tsrange * 30000)" | |
}, | |
{ | |
"name": "endts", "value": 1568152000000, "update": "centerts + (tsrange * 30000)" | |
}, | |
{ | |
"name": "tickMinor", "update": "(tsrange < 60) ? 5 : (tsrange < 120) ? 10 : 15" | |
}, | |
{ | |
"name": "tickMajor", "update": "tickMinor * 4" | |
}, | |
{ | |
"name": "savebookmark", | |
"on": [{ | |
"events": "window:keydown[event.shiftKey && (event.keyCode>48) && (event.keyCode<59) ]", | |
"update": "warn('save ', event.keyCode - 49, (isDefined(data('bookmarks')[event.keyCode - 49])) ? data('bookmarks')[event.keyCode - 49] : null)" | |
}, { | |
"events": "window:keyup[event.shiftKey && (event.keyCode>48) && (event.keyCode<59) ]", | |
"update": "null" | |
}] | |
}, | |
{ | |
"name": "bmspacing", "value": 30 | |
} | |
], | |
"data": [{ | |
"name": "window", | |
"values": [ | |
{ "from": 1000, "to": 1567296000000, "fill": "#222", "radius": 0 }, | |
{ "from": 1569801600000, "to": 9569801600000, "fill": "#5511117b", "radius": 0 } | |
] | |
}, { | |
"name": "bookmarks", | |
"on":[{ | |
"trigger": "savebookmark", | |
"modify": "savebookmark", | |
"values": "{ ts: centerts }" | |
}], | |
"values": [ | |
{ "shortcut": "1", "ts": 1568159000000 }, | |
{ "shortcut": "2", "ts": 1568162000000 }, | |
{ "shortcut": "3", "ts": 1568166000000 }, | |
{ "shortcut": "4", "ts": 1569024000000 }, | |
{ "shortcut": "5", "ts": 0 }, | |
{ "shortcut": "6", "ts": 0 }, | |
{ "shortcut": "7", "ts": 0 }, | |
{ "shortcut": "8", "ts": 0 }, | |
{ "shortcut": "9", "ts": 0 } | |
] | |
}, { | |
"name": "BMLT", | |
"source": "bookmarks", | |
"transform": [{ | |
"type": "filter", | |
"expr": "datum.ts>0 && datum.ts < startts" | |
}] | |
}, { | |
"name": "BMV", | |
"source": "bookmarks", | |
"transform": [{ | |
"type": "filter", | |
"expr": "datum.ts > startts && datum.ts < endts" | |
}] | |
}, { | |
"name": "BMGT", | |
"source": "bookmarks", | |
"transform": [{ | |
"type": "filter", | |
"expr": "datum.ts > endts" | |
}] | |
}], | |
"scales": [ | |
{ | |
"name": "lin_timescale", | |
"type": "linear", | |
"domain": [{"signal": "startts"}, {"signal": "endts"}], | |
"nice": false, | |
"zero": false, | |
"range": "width" | |
}, { | |
"name": "timescale", | |
"type": "time", | |
"domain": { "signal": "domain('lin_timescale')" }, | |
"nice": false, | |
"clamp": true, | |
"range": "width" | |
}, { | |
"name": "bands", | |
"type": "band", | |
"paddingInner": 0.04, | |
"domain": [0, 1, 2, 3, 4, 5], | |
"range": "height" | |
} | |
], | |
"axes": [ | |
{ | |
"orient": "top", "scale": "timescale", "domain": false, | |
"tickCount": { "interval": "minute", "step": 5 }, | |
"labels": false, | |
"grid": true, | |
"gridWidth": 2, | |
"gridColor": "#888", | |
"zindex": -1, | |
"encode": { | |
"grid": { | |
"update": { | |
"y": { "scale": "bands", "value": 2 }, | |
"y2": { "scale": "bands", "value": 3 } | |
} | |
} | |
} | |
}, | |
{ | |
"orient": "top", "scale": "timescale", "domain": false, | |
"tickCount": { "interval": "minute", "step": 15 }, | |
"labelOverlap": "greedy", | |
"grid": true, | |
"gridWidth": 2, | |
"gridColor": "#888", | |
"zindex": -1, | |
"format": "%H:%M", | |
"encode": { | |
"grid": { | |
"update": { | |
"y": { "scale": "bands", "value": 1 }, | |
"y2": { "scale": "bands", "value": 4 } | |
} | |
} | |
} | |
}, | |
{ | |
"orient": "bottom", "scale": "timescale", "domain": false, | |
"tickCount": { "interval": "hour", "step": 1 }, | |
"labels": true, | |
"labelColor": "white", | |
"grid": true, | |
"gridWidth": 3, | |
"gridColor": "#888", | |
"zindex": -1, | |
"format": "%b%d %-I%p", | |
"encode": { | |
"labels": { | |
"update": { | |
"y": { "value": 9 }, | |
"y2": { "scale": "bands", "value": 1 } | |
} | |
} | |
} | |
} | |
], | |
"marks": [ | |
{ | |
"name": "bars", | |
"from": {"data": "window"}, | |
"type": "rect", | |
"encode": { | |
"enter": { | |
"y": {"scale": "bands", "value": 0, "offset": -4 }, | |
"height": {"scale": "bands", "band": 6, "offset": 9 } | |
}, | |
"update": { | |
"x": {"scale": "timescale", "field": "from"}, | |
"x2": {"scale": "timescale", "field": "to"}, | |
"cornerRadius": { "field": "radius" }, | |
"fill": { "field": "fill"}, | |
"stroke": { "field": "stroke"}, | |
"strokeWidth": { "field": "strokeWidth"} | |
} | |
} | |
}, | |
{ | |
"name": "bookmarksGroup", | |
"type": "group", | |
"signals": [{ | |
"name": "bmlt_width", | |
"update": "data('BMLT').length * bmspacing" | |
}, { | |
"name": "bmgt_width", | |
"update": "data('BMGT').length * bmspacing" | |
}], | |
"scales": [{ | |
"name": "bmlt_scale", | |
"type": "point", | |
"align": 0, | |
"domain": { | |
"data": "BMLT", | |
"field": "shortcut", | |
"sort": {"op": "median", "field": "ts", "order": "ascending"} | |
}, | |
"range": { "step": { "signal": "bmspacing" } } | |
}, { | |
"name": "bmgt_scale", | |
"type": "point", | |
"align": 0, | |
"domain": { | |
"data": "BMGT", | |
"field": "shortcut", | |
"sort": {"op": "median", "field": "ts", "order": "descending"} | |
}, | |
"range": { "step": { "signal": "bmspacing" } } | |
}, { | |
"name": "timescale_bmv", | |
"type": "linear", | |
"domain": [ | |
{ "signal": "invert('lin_timescale', bmlt_width)" }, | |
{ "signal": "invert('lin_timescale', width - bmgt_width )" } | |
], | |
"nice": false, | |
"clamp": true, | |
"zero": false, | |
"range": [{ "signal": "bmlt_width" }, { "signal": "width - bmgt_width" }] | |
}], | |
"marks": [ | |
{ | |
"name": "BMPointers", | |
"from": {"data": "BMV"}, | |
"type": "symbol", | |
"encode": { | |
"enter": { | |
"shape": {"value": "wedge"}, | |
"y": {"scale": "bands", "value": 4, "offset": 7 }, | |
"size": { "value": 500 }, | |
"zindex": { "value": 5 }, | |
"fill": { "value": "#00bfff"} | |
}, | |
"update": { | |
"x": {"scale": "timescale", "field": "ts" } | |
} | |
} | |
}, | |
{ | |
"name": "BMLTSquares", | |
"from": {"data": "BMLT"}, | |
"type": "rect", | |
"encode": { | |
"enter": { | |
"y": {"scale": "bands", "value": 5 }, | |
"width": { "value": 20 }, | |
"height": { "value": 20 }, | |
"fill": { "value": "#00bfff"}, | |
"zindex": { "value": 5 }, | |
"cornerRadius": { "value": 4 } | |
}, | |
"update": { | |
"x": { "scale": "bmlt_scale", "field": "shortcut", "offset": -10 } | |
} | |
} | |
}, { | |
"name": "BMLTLabels", | |
"from": {"data": "BMLT"}, | |
"type": "text", | |
"encode": { | |
"enter": { | |
"text": {"field": "shortcut"}, | |
"align": { "value": "center" }, | |
"baseline": { "value": "top" }, | |
"fontSize": { "value": 14 }, | |
"y": {"scale": "bands", "value": 5, "offset": 4 }, | |
"size": { "value": 200 }, | |
"fill": { "value": "white"} | |
}, | |
"update": { | |
"x": { "scale": "bmlt_scale", "field": "shortcut" } | |
} | |
} | |
}, | |
{ | |
"name": "BMCVSquares", | |
"from": {"data": "BMV"}, | |
"type": "rect", | |
"encode": { | |
"enter": { | |
"y": {"scale": "bands", "value": 5 }, | |
"width": { "value": 20 }, | |
"height": { "value": 20 }, | |
"fill": { "value": "#00bfff"}, | |
"zindex": { "value": 5 }, | |
"cornerRadius": { "value": 4 } | |
}, | |
"update": { | |
"x": {"scale": "timescale_bmv", "field": "ts", "offset": -10 } | |
} | |
} | |
}, { | |
"name": "BMCVLabels", | |
"from": {"data": "BMV"}, | |
"type": "text", | |
"encode": { | |
"enter": { | |
"text": {"field": "shortcut"}, | |
"align": { "value": "center" }, | |
"baseline": { "value": "top" }, | |
"fontSize": { "value": 14 }, | |
"y": {"scale": "bands", "value": 5, "offset": 4 }, | |
"size": { "value": 200 }, | |
"zindex": { "value": 5 }, | |
"fill": { "value": "white"} | |
}, | |
"update": { | |
"x": {"scale": "timescale_bmv", "field": "ts" } | |
} | |
} | |
}, | |
{ | |
"name": "BMGTSquares", | |
"from": {"data": "BMGT"}, | |
"type": "rect", | |
"zindex": { "value": 50 }, | |
"encode": { | |
"enter": { | |
"y": {"scale": "bands", "value": 5 }, | |
"width": { "value": 20 }, | |
"height": { "value": 20 }, | |
"fill": { "value": "#00bfff"}, | |
"zindex": { "value": 5 }, | |
"cornerRadius": { "value": 4 } | |
}, | |
"update": { | |
"x": { "signal": "width-10", "offset": { "scale": "bmgt_scale", "field": "shortcut", "mult": -1 } } | |
} | |
} | |
}, { | |
"name": "BMGTLabels", | |
"from": {"data": "BMGT"}, | |
"type": "text", | |
"encode": { | |
"enter": { | |
"text": {"field": "shortcut"}, | |
"align": { "value": "center" }, | |
"baseline": { "value": "top" }, | |
"fontSize": { "value": 14 }, | |
"y": {"scale": "bands", "value": 5, "offset": 4 }, | |
"size": { "value": 200 }, | |
"zindex": { "value": 5 }, | |
"fill": { "value": "white"} | |
}, | |
"update": { | |
"x": { "signal": "width", "offset": { "scale": "bmgt_scale", "field": "shortcut", "mult": -1 } } | |
} | |
} | |
} | |
] | |
}] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment