Last active
February 6, 2025 19:53
-
-
Save Giammaria/6d489d8ef1d28019ce19c7bb39b657a3 to your computer and use it in GitHub Desktop.
20241116_sf_mousewheel_measures_poc_v
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", | |
"height": 300, | |
"autosize": {"type": "fit-x", "resize": true}, | |
"signals": [ | |
{ | |
"name": "desiredWidth", | |
"value": 1000, | |
"update": "clamp(desiredWidth, 200, 1400)" | |
}, | |
{ | |
"name": "columnsWidthPercent", | |
"value": 0, | |
"update": "clamp(columnsWidthPercent, 0, 0.5)" | |
}, | |
{ | |
"name": "offsetUnit", | |
"value": "hour", | |
"update": "indexof(['hours', 'day', 'month', 'year'], offsetUnit) < 0 ? 'month' : offsetUnit" | |
}, | |
{ | |
"name": "negativeDateOffsetFromToday", | |
"value": -5, | |
"update": "clamp(negativeDateOffsetFromToday, -10, 0)" | |
}, | |
{ | |
"name": "positiveOffsetFromToday", | |
"value": 5, | |
"update": "clamp(positiveOffsetFromToday, 1, 10)" | |
}, | |
{"name": "recordCount", "value": 5, "update": "clamp(recordCount, 1, 100)"}, | |
{ | |
"name": "blockHeight", | |
"value": 15, | |
"update": "clamp(blockHeight, 10, 50)" | |
}, | |
{"name": "columnsWidth", "update": "desiredWidth*columnsWidthPercent"}, | |
{"name": "ganttWidth", "update": "desiredWidth*(1-columnsWidthPercent)"}, | |
{ | |
"name": "configToggleMouseWheelGranularity", | |
"description": "configurations for the mouse wheel granularity control", | |
"update": "{enabled: true, initialValue: false, xOffset: 0, track: {height: 7.5, width: 25, cornerRadius: 5, fill: '#EEE', stroke: '#777', strokeWidth: 1}, handle: {stroke: '#777', strokeWidth: 1, fill: '#fff'}, label: {text: 'Mouse wheel granularity', font: 'Segoe UI', fontSize: 12, fill: '#666', fontStyle: 'regular', dx: 5}, on: {fill: '#d1e0ec', fillOpacity: 1, stroke: '#777', strokeWidth: 1}, tooltip: {object: {title: 'Mouse Wheel Date Granularity', '• ': 'Click here to toggle the ability to adjust date granularity using the mouse wheel.', '• ': 'Alternatively, press the Ctrl key to quickly toggle this capability on or off.', '':'', 'Note': 'When toggled off, the mouse wheel will allow for vertical scrolling when necessary.'}}}" | |
}, | |
{ | |
"name": "todayDate", | |
"update": "utc(year(now()),month(now()),date(now()))" | |
}, | |
{ | |
"name": "scrollDomain", | |
"update": "[xDomainBounds.max+span(xDomainInitial)/2, ((initialDomainCenter - xDomainBounds.max)+initialDomainCenter)-span(xDomainInitial)/2]" | |
}, | |
{ | |
"name": "horizontalScrollPercentage", | |
"init": "{current: 0.5, previous: 0.5, debug: 'start'}", | |
"on": [ | |
{ | |
"events": { | |
"type": "pointermove", | |
"source": "scope", | |
"consume": true, | |
"markname": "gantt-mini-map-interactive-rect", | |
"debounce": 10, | |
"between": [{"type": "pointerdown"}, {"type": "pointerup"}] | |
}, | |
"update": "inrange(invert('xScaleMiniMap', x(group())-60), xDomain) ? horizontalScrollPercentage : {current: clamp(1-((domain('xScaleMiniMap')[1] - +invert('xScaleMiniMap', x(group())-60) + ((1-((domain('xScaleMiniMap')[1] - +invert('xScaleMiniMap', x(group())-60)))/span(domain('xScaleMiniMap'))) < horizontalScrollPercentage.current ? 0 : span(xDomain))))/span(domain('xScaleMiniMap')), 0,1), previous: horizontalScrollPercentage.current === 0 ? span(xDomain)/span(domain('xScaleMiniMap')) : horizontalScrollPercentage.current}" | |
}, | |
{ | |
"events": { | |
"type": "pointerdown", | |
"source": "scope", | |
"consume": true, | |
"markname": "gantt-mini-map-interactive-rect" | |
}, | |
"update": "inrange(invert('xScaleMiniMap', x(group())), xDomain) ? horizontalScrollPercentage : {current: clamp(1-((domain('xScaleMiniMap')[1]- +invert('xScaleMiniMap', x(group()))+span(xDomain)/2))/span(domain('xScaleMiniMap')), 0,1), previous: horizontalScrollPercentage.current === 0 ? span(xDomain)/span(domain('xScaleMiniMap')) : horizontalScrollPercentage.current}" | |
}, | |
{ | |
"events": {"type": "pointerup"}, | |
"update": "horizontalScrollPercentage" | |
}, | |
{ | |
"events": "window:keydown", | |
"update": "indexof(['ArrowRight', 'ArrowLeft'], event.code) < 0 ? horizontalScrollPercentage : event.code === 'ArrowRight' ? {current: clamp(horizontalScrollPercentage.current+0.01, 0,1), previous: clamp(horizontalScrollPercentage.current, 0.01, 0.99)} : {current: clamp(horizontalScrollPercentage.current-0.01, 0,1), previous: clamp(horizontalScrollPercentage.current, 0.01, 0.99)}" | |
} | |
] | |
}, | |
{"name": "minDateBandwidth", "value": 20}, | |
{ | |
"name": "mouseWheelGranularity", | |
"description": "the currently toggled value for the mouse wheel granularity control", | |
"init": "configToggleMouseWheelGranularity.initialValue", | |
"on": [ | |
{ | |
"events": "@mouseWheel-granularity-clickable-rect:pointerdown", | |
"update": "!mouseWheelGranularity" | |
}, | |
{ | |
"events": "window:keydown[event.ctrlKey]{0, 100}", | |
"update": "mouseWheelGranularity ? false : true" | |
} | |
] | |
}, | |
{ | |
"name": "wheelDelta", | |
"value": 0, | |
"on": [ | |
{ | |
"events": "wheel!", | |
"force": true, | |
"update": "mouseWheelGranularity && x()>columnsWidth?pow(1.001, (event.deltaY) * pow(16, event.deltaMode)) : 0" | |
}, | |
{ | |
"events": "wheel![event.ctrlKey]", | |
"force": true, | |
"update": "x()>columnsWidth?pow(1.001, (event.deltaY) * pow(16, event.deltaMode)) : 0" | |
} | |
] | |
}, | |
{ | |
"name": "zoom", | |
"value": 1, | |
"on": [ | |
{ | |
"events": "wheel!", | |
"force": true, | |
"update": "!mouseWheelGranularity || wheelDelta === 0 ? zoom : wheelDelta" | |
} | |
] | |
}, | |
{"name": "xDomainInitial", "update": "data('xDomainInitial')[0]['domain']"}, | |
{ | |
"name": "initialDomainCenter", | |
"update": "xDomainInitial[0] + span(xDomainInitial) / 2" | |
}, | |
{ | |
"name": "currentDomainCenter", | |
"init": "initialDomainCenter", | |
"on": [ | |
{ | |
"events": {"signal": "horizontalScrollPercentage.current"}, | |
"update": "xDomain[0] + span(xDomain) / 2" | |
}, | |
{ | |
"events": {"signal": "xDomain"}, | |
"update": "xDomain[0] + span(xDomain) / 2" | |
} | |
] | |
}, | |
{ | |
"name": "xDomainBounds", | |
"update": "{min: span(data('xDomainInitial')[0]['hourDomain']), max: round((ganttWidth/0.075)* scale('dateUnitIncrementMS', 'day'))}" | |
}, | |
{ | |
"name": "xDomain", | |
"init": "xDomainInitial", | |
"on": [ | |
{ | |
"events": {"signal": "xDomainPreliminary"}, | |
"update": "span(xDomainPreliminary)<xDomainBounds.min ? [currentDomainCenter - xDomainBounds.min/2, currentDomainCenter + xDomainBounds.min/2] : [max(xDomainPreliminary[0], scrollDomain[0]), min(xDomainPreliminary[1], scrollDomain[1])]" | |
} | |
] | |
}, | |
{ | |
"name": "xDomainPreliminary", | |
"value": [0, 0], | |
"on": [ | |
{ | |
"events": {"signal": "zoom"}, | |
"update": "wheelDelta === 0 ? xDomainPreliminary : [currentDomainCenter + (xDomain[0] - currentDomainCenter) * zoom, currentDomainCenter + (xDomain[1] - currentDomainCenter) * zoom]" | |
}, | |
{ | |
"events": {"signal": "horizontalScrollPercentage.current"}, | |
"update": "[min(scale('scaleXScroll', horizontalScrollPercentage.current), scale('scaleXScroll', 1)-span(xDomain)), span(xDomain)+scale('scaleXScroll', horizontalScrollPercentage.current)]" | |
} | |
] | |
}, | |
{"name": "today", "update": "utc(year(now()),month(now()),date(now()))"}, | |
{ | |
"name": "currentXBandwidth", | |
"update": "(round((scale('x', timeOffset('hours', utchours(0,0,0,0),1)) - scale('x', utchours(0,0,0,0))) *100)/100)" | |
}, | |
{"name": "thresholdMinuteBandwidth", "update": "17.78"}, | |
{"name": "thresholdHourBandwidth", "update": "0.6"}, | |
{"name": "thresholdDayBandwidth", "update": "0.26"}, | |
{"name": "thresholdMonthBandwidth", "update": "0.04"}, | |
{"name": "thresholdYearBandwidth", "update": "0.03"}, | |
{ | |
"name": "xCurrentUnit", | |
"update": "(currentXBandwidth>=thresholdMinuteBandwidth ? 'hour': currentXBandwidth>=thresholdHourBandwidth ? 'day' : currentXBandwidth >= thresholdDayBandwidth ? 'month' : currentXBandwidth >= thresholdMonthBandwidth ? 'month' : 'year')" | |
}, | |
{ | |
"name": "xCurrentDateFormat", | |
"update": "['%H', '%d', currentXBandwidth >= 0.12 ? '%B %Y' : '%b', '%Y'][indexof(['hour', 'day', 'month', 'year'],xCurrentUnit)]" | |
}, | |
{ | |
"name": "xCurrentDateLabelDX", | |
"update": "xCurrentUnit === 'hour' ? ((scale('x', utchours(0,0,0,0))-scale('x', timeOffset('hours', utchours(0,0,0,0), -1)))/2) : (scale('x', now())-scale('x', timeOffset(xCurrentUnit, now(), -1)))/2" | |
}, | |
{ | |
"name": "xCurrentUnitOffset", | |
"update": "xCurrentUnit === 'year' ? null : ['hour', 'day', 'month', 'year'][indexof(['hour','day', 'month'], xCurrentUnit)+1]" | |
}, | |
{ | |
"name": "xCurrentDateFormatOffset", | |
"update": "['%H', '%d %B %Y', '%B %Y', '%Y'][indexof(['hour', 'day', 'month', 'year'],xCurrentUnitOffset)]" | |
}, | |
{ | |
"name": "xCurrentDateOffsetLabelDX", | |
"update": "xCurrentUnitOffset === 'hour' ? ((scale('x', utchours(0,0,0,0))-scale('x', timeOffset('hours', utchours(0,0,0,0), -1)))/2) : (scale('x', now())-scale('x', timeOffset(xCurrentUnitOffset, now(), -1)))/2" | |
}, | |
{"name": "miniMapHeight", "value": 10}, | |
{ | |
"name": "ganttMiniMapMouseDown", | |
"description": "boolean indicating whether the horizontal mini-map scrollbar is currently being clicked", | |
"value": false, | |
"on": [ | |
{ | |
"events": "@gantt-mini-map-interactive-rect:pointerdown", | |
"update": "true" | |
}, | |
{"events": {"type": "pointerup"}, "update": "false"} | |
] | |
}, | |
{ | |
"name": "ganttMiniMapX", | |
"value": null, | |
"on": [ | |
{ | |
"events": "@gantt-mini-map-interactive-rect:pointerdown", | |
"update": "1-((domain('xScaleMiniMap')[1]- +invert('xScaleMiniMap', x(group())))/span(domain('xScaleMiniMap')))" | |
}, | |
{"events": {"type": "pointerup"}, "update": "null"} | |
] | |
}, | |
{ | |
"name": "ganttMiniMapMouseOver", | |
"description": "boolean indicating whether the horizontal mini-map scrollbar is currently being moused over", | |
"value": false, | |
"on": [ | |
{ | |
"events": "@gantt-mini-map-interactive-rect:mouseover", | |
"update": "true" | |
}, | |
{ | |
"events": "@gantt-mini-map-interactive-rect:mouseout", | |
"update": "false" | |
} | |
] | |
}, | |
{"name": "width", "update": "desiredWidth"}, | |
{ | |
"name": "padding", | |
"update": "{'top': 5, 'right': 5, 'bottom': ganttMiniMapMouseDown ? 0 : 5, 'left': 5}" | |
}, | |
{"name": "showDebugArea", "value": false} | |
], | |
"marks": [ | |
{ | |
"name": "group-header", | |
"type": "group", | |
"encode": { | |
"update": { | |
"x": {"value": 0}, | |
"width": {"signal": "desiredWidth"}, | |
"height": {"signal": "20"}, | |
"y": {"value": -50} | |
} | |
}, | |
"marks": [ | |
{ | |
"name": "group_mouseWheelGranularity", | |
"description": "group for the marks that make up the toggle control to hide/show details", | |
"type": "group", | |
"interactive": false, | |
"clip": false, | |
"encode": { | |
"update": { | |
"y": {"value": 0}, | |
"x": {"signal": "columnsWidth+ganttWidth-2.5"} | |
} | |
}, | |
"marks": [ | |
{ | |
"name": "track_rect", | |
"description": "the track for the toggle control", | |
"type": "rect", | |
"interactive": false, | |
"encode": { | |
"update": { | |
"y": { | |
"signal": "configToggleMouseWheelGranularity.track.height/2" | |
}, | |
"height": { | |
"signal": "configToggleMouseWheelGranularity.track.height" | |
}, | |
"x": { | |
"signal": "-configToggleMouseWheelGranularity.track.width-5" | |
}, | |
"width": { | |
"signal": "configToggleMouseWheelGranularity.track.width" | |
}, | |
"cornerRadius": { | |
"signal": "configToggleMouseWheelGranularity.track.cornerRadius" | |
}, | |
"fill": { | |
"signal": "mouseWheelGranularity ? configToggleMouseWheelGranularity.on.fill : configToggleMouseWheelGranularity.track.fill" | |
}, | |
"stroke": { | |
"signal": "configToggleMouseWheelGranularity.track.stroke" | |
}, | |
"strokeWidth": { | |
"signal": "configToggleMouseWheelGranularity.track.strokeWidth" | |
} | |
} | |
} | |
}, | |
{ | |
"name": "toggle_outer_arc", | |
"description": "the circle mark that serves as the the 'toggle handle'", | |
"from": {"data": "track_rect"}, | |
"type": "arc", | |
"interactive": false, | |
"encode": { | |
"enter": { | |
"y": { | |
"signal": "datum.bounds.y1+configToggleMouseWheelGranularity.track.height/2" | |
}, | |
"innerRadius": {"value": 0}, | |
"outerRadius": { | |
"signal": "configToggleMouseWheelGranularity.track.height*0.9" | |
}, | |
"startAngle": {"signal": "0"}, | |
"endAngle": {"signal": "2*PI"}, | |
"stroke": { | |
"signal": "configToggleMouseWheelGranularity.handle.stroke || '#BBB'" | |
}, | |
"strokeWidth": { | |
"signal": "configToggleMouseWheelGranularity.handle.strokeWidth" | |
}, | |
"fill": { | |
"signal": "configToggleMouseWheelGranularity.handle.fill || '#fff'" | |
} | |
}, | |
"update": { | |
"x": { | |
"signal": "mouseWheelGranularity ? datum.bounds.x2-configToggleMouseWheelGranularity.track.height*0.9 : datum.bounds.x1+configToggleMouseWheelGranularity.track.height*0.9" | |
} | |
} | |
} | |
}, | |
{ | |
"name": "mouseWheelGranularity_text", | |
"description": "the title for the toggle control", | |
"type": "text", | |
"from": {"data": "track_rect"}, | |
"interactive": false, | |
"encode": { | |
"update": { | |
"x": {"signal": "datum.bounds.x1"}, | |
"dx": { | |
"signal": "-configToggleMouseWheelGranularity.label.dx" | |
}, | |
"y": { | |
"signal": "datum.bounds.y1+(datum.bounds.y2-datum.bounds.y1)/2" | |
}, | |
"text": { | |
"signal": "configToggleMouseWheelGranularity.label.text || ''" | |
}, | |
"baseline": {"value": "middle"}, | |
"font": { | |
"signal": "configToggleMouseWheelGranularity.label.font" | |
}, | |
"fontSize": { | |
"signal": "configToggleMouseWheelGranularity.label.fontSize" | |
}, | |
"fontStyle": { | |
"signal": "configToggleMouseWheelGranularity.label.fontStyle" | |
}, | |
"align": {"value": "right"}, | |
"fill": { | |
"signal": "configToggleMouseWheelGranularity.label.fill" | |
} | |
} | |
} | |
} | |
] | |
}, | |
{ | |
"name": "mouseWheel-granularity-clickable-rect", | |
"type": "rect", | |
"from": {"data": "group_mouseWheelGranularity"}, | |
"interactive": true, | |
"encode": { | |
"update": { | |
"y": {"signal": "datum.bounds.y1"}, | |
"y2": {"signal": "datum.bounds.y2"}, | |
"x": {"signal": "datum.bounds.x1"}, | |
"x2": {"signal": "datum.bounds.x2"}, | |
"fill": {"value": "transparent"}, | |
"tooltip": { | |
"signal": "configToggleMouseWheelGranularity.tooltip.object" | |
}, | |
"cursor": {"value": "pointer"} | |
} | |
} | |
} | |
] | |
}, | |
{ | |
"name": "rect-background", | |
"type": "rect", | |
"encode": { | |
"update": { | |
"width": {"signal": "desiredWidth-1"}, | |
"height": {"signal": "height"}, | |
"fill": {"value": "transparent"}, | |
"stroke": {"value": "#AAA"}, | |
"strokeWidth": {"value": 0.1} | |
} | |
} | |
}, | |
{ | |
"name": "rect-gantt-background", | |
"type": "rect", | |
"encode": { | |
"update": { | |
"x": {"signal": "columnsWidth"}, | |
"width": {"signal": "ganttWidth-1"}, | |
"height": {"signal": "height"}, | |
"fill": {"value": "transparent"}, | |
"stroke": {"value": "#AAA"}, | |
"strokeWidth": {"value": 0.1} | |
} | |
} | |
}, | |
{ | |
"name": "group-gantt-mini-map", | |
"type": "group", | |
"encode": { | |
"update": { | |
"x": {"signal": "ganttMiniMapMouseDown ? 0 : 60"}, | |
"y": {"signal": "ganttMiniMapMouseDown ? 0 : height+5"} | |
} | |
}, | |
"marks": [ | |
{ | |
"name": "track", | |
"type": "rect", | |
"encode": { | |
"update": { | |
"x": {"signal": "ganttMiniMapMouseDown ? 60 : 0"}, | |
"width": {"signal": "range('xScaleMiniMap')[1]"}, | |
"y": { | |
"signal": "(ganttMiniMapMouseDown ? height+5 : 0) + miniMapHeight/2", | |
"offset": -0.15 | |
}, | |
"height": {"value": 0.3}, | |
"fill": {"value": "#AAA"}, | |
"opacity": { | |
"signal": "scale('xScaleMiniMap', xDomain[0]) === range('xScaleMiniMap')[0] ? 0 : 1" | |
} | |
} | |
} | |
}, | |
{ | |
"name": "rect-domain-max-brush", | |
"type": "rect", | |
"from": {"data": "track"}, | |
"encode": { | |
"update": { | |
"y": {"signal": "datum.bounds.y1 - miniMapHeight/2"}, | |
"x": { | |
"scale": "xScaleMiniMap", | |
"signal": "xDomain[0]", | |
"offset": {"signal": "(ganttMiniMapMouseDown ? 60 : 0) -0.5"} | |
}, | |
"x2": { | |
"scale": "xScaleMiniMap", | |
"signal": "xDomain[1]", | |
"offset": {"signal": "(ganttMiniMapMouseDown ? 60 : 0) + 0.5"} | |
}, | |
"height": {"signal": "miniMapHeight"}, | |
"fill": {"signal": "ganttMiniMapMouseOver ? '#eee' : '#fff'"}, | |
"opacity": { | |
"signal": "scale('xScaleMiniMap', xDomain[0]) === range('xScaleMiniMap')[0] ? 0 : 1" | |
} | |
} | |
} | |
}, | |
{ | |
"name": "time-series-rect", | |
"type": "rect", | |
"from": {"data": "track"}, | |
"encode": { | |
"update": { | |
"x": { | |
"signal": "datum.bounds.x1+scale('xScaleMiniMap', xDomainInitial[0])" | |
}, | |
"x2": { | |
"signal": "datum.bounds.x1+scale('xScaleMiniMap', xDomainInitial[1])" | |
}, | |
"y": { | |
"signal": "datum.bounds.y1+(datum.bounds.y2-datum.bounds.y1)/2" | |
}, | |
"y2": { | |
"signal": "datum.bounds.y1+(datum.bounds.y2-datum.bounds.y1)/2" | |
}, | |
"strokeWidth": {"signal": "miniMapHeight/2"}, | |
"stroke": {"value": "#BCC9D4"}, | |
"fill": {"value": "transparent"}, | |
"cursor": { | |
"signal": "(ganttMiniMapMouseOver || ganttMiniMapMouseDown) && scale('xScaleMiniMap', xDomain[0]) !== range('xScaleMiniMap')[0] ? 'pointer' : 'default'" | |
} | |
} | |
} | |
}, | |
{ | |
"name": "rect-domain-min-tick", | |
"from": {"data": "rect-domain-max-brush"}, | |
"type": "rect", | |
"encode": { | |
"update": { | |
"x": {"signal": "datum.bounds.x1"}, | |
"y": {"signal": "datum.bounds.y1"}, | |
"width": {"value": 1}, | |
"height": {"signal": "miniMapHeight"}, | |
"fill": {"value": "#000"}, | |
"opacity": { | |
"signal": "xDomain[0] <= scrollDomain[0] && xDomain[1] >= scrollDomain[1] ? 0 : 1" | |
} | |
} | |
} | |
}, | |
{ | |
"name": "rect-domain-max-tick", | |
"from": {"data": "rect-domain-max-brush"}, | |
"type": "rect", | |
"encode": { | |
"update": { | |
"x": {"signal": "datum.bounds.x2"}, | |
"y": {"signal": "datum.bounds.y1"}, | |
"width": {"value": 1}, | |
"height": {"signal": "miniMapHeight"}, | |
"fill": {"value": "#000"}, | |
"opacity": { | |
"signal": "xDomain[0] <= scrollDomain[0] && xDomain[1] >= scrollDomain[1] ? 0 : 1" | |
} | |
} | |
} | |
}, | |
{ | |
"name": "text-date-unit-label", | |
"type": "text", | |
"from": {"data": "track"}, | |
"encode": { | |
"update": { | |
"x": {"signal": "datum.bounds.x1-60+5"}, | |
"y": {"signal": "datum.bounds.y1"}, | |
"baseline": {"value": "middle"}, | |
"text": { | |
"signal": "upper(substring(xCurrentUnit, 0, 1))+substring(xCurrentUnit, 1, length(xCurrentUnit))+' View'" | |
}, | |
"fontSize": {"value": 9}, | |
"fill": {"value": "#666"} | |
} | |
} | |
}, | |
{ | |
"name": "text-date-granularity-reset-label", | |
"type": "text", | |
"from": {"data": "track"}, | |
"encode": { | |
"update": { | |
"x": {"signal": "datum.bounds.x2+10"}, | |
"y": {"signal": "datum.bounds.y1"}, | |
"baseline": {"value": "middle"}, | |
"text": { | |
"signal": "'Reset'" | |
}, | |
"fontSize": {"value": 9}, | |
"fill": {"value": "#666"} | |
} | |
} | |
}, | |
{ | |
"name": "gantt-mini-map-interactive-rect", | |
"type": "rect", | |
"from": {"data": "track"}, | |
"encode": { | |
"update": { | |
"x": {"signal": "ganttMiniMapMouseDown ? 0 : datum.bounds.x1"}, | |
"x2": { | |
"signal": "(ganttMiniMapMouseDown ? padding.right*4 : 0) + datum.bounds.x2" | |
}, | |
"y": { | |
"signal": "ganttMiniMapMouseDown ? 0 : datum.bounds.y1 - miniMapHeight/2-5" | |
}, | |
"y2": { | |
"signal": "datum.bounds.y2 + miniMapHeight/2+10 + (ganttMiniMapMouseDown ? 5 : 0)" | |
}, | |
"fillOpacity": {"value": 0}, | |
"cursor": { | |
"signal": "(ganttMiniMapMouseOver || ganttMiniMapMouseDown) && scale('xScaleMiniMap', xDomain[0]) !== range('xScaleMiniMap')[0] ? 'pointer' : 'default'" | |
} | |
} | |
} | |
} | |
] | |
}, | |
{ | |
"name": "footer-divider", | |
"type": "rect", | |
"interactive": false, | |
"encode": { | |
"update": { | |
"x": {"value": 0}, | |
"width": {"signal": "showDebugArea ? desiredWidth : 0"}, | |
"y": {"signal": "showDebugArea ? height+40 : 0"}, | |
"height": {"value": 0}, | |
"stroke": {"value": "#000"}, | |
"strokeWidth": {"signal": "showDebugArea ? 0.5 : 0"} | |
} | |
} | |
}, | |
{ | |
"name": "config-group", | |
"type": "group", | |
"from": {"data": "footer-divider"}, | |
"interactive": false, | |
"encode": {"update": {"y": {"signal": "datum.bounds.y2", "offset": 5}}}, | |
"marks": [ | |
{ | |
"name": "config-labels", | |
"from": {"data": "configurations"}, | |
"type": "text", | |
"encode": { | |
"update": { | |
"y": {"signal": "showDebugArea ? (datum.index-1)*14 : 0"}, | |
"text": {"signal": "showDebugArea ? datum.label : null"}, | |
"baseline": {"value": "top"}, | |
"fill": {"value": "#333"} | |
} | |
} | |
}, | |
{ | |
"name": "config-values", | |
"from": {"data": "config-labels"}, | |
"type": "text", | |
"encode": { | |
"update": { | |
"x": {"signal": "datum.bounds.x2", "offset": 5}, | |
"y": {"signal": "showDebugArea ? datum.y : null"}, | |
"text": {"signal": "showDebugArea ? datum.datum.value : null"}, | |
"baseline": {"value": "top"}, | |
"fontWeight": {"value": 600} | |
} | |
} | |
} | |
] | |
}, | |
{ | |
"name": "properties-group", | |
"type": "group", | |
"from": {"data": "footer-divider"}, | |
"interactive": false, | |
"encode": { | |
"update": { | |
"x": {"signal": "desiredWidth/2"}, | |
"y": {"signal": "datum.bounds.y2", "offset": 5} | |
} | |
}, | |
"marks": [ | |
{ | |
"name": "property-labels", | |
"from": {"data": "properties"}, | |
"type": "text", | |
"encode": { | |
"update": { | |
"y": {"signal": "showDebugArea ? (datum.index-1)*14 : 0"}, | |
"text": {"signal": "showDebugArea ? datum.label : null"}, | |
"baseline": {"value": "top"}, | |
"fill": {"value": "#333"} | |
} | |
} | |
}, | |
{ | |
"name": "property-values", | |
"from": {"data": "property-labels"}, | |
"type": "text", | |
"encode": { | |
"update": { | |
"x": {"signal": "datum.bounds.x2", "offset": 5}, | |
"y": {"signal": "showDebugArea ? datum.y : 0"}, | |
"text": {"signal": "showDebugArea ? datum.datum.value : null"}, | |
"baseline": {"value": "top"}, | |
"fontWeight": {"value": 600} | |
} | |
} | |
} | |
] | |
} | |
], | |
"scales": [ | |
{ | |
"name": "dateUnitIncrementMS", | |
"type": "ordinal", | |
"domain": ["hours", "day", "month", "year"], | |
"range": [3600000, 86400000, 2628000000, 31540000000] | |
}, | |
{ | |
"name": "x", | |
"type": "time", | |
"domain": {"signal": "xDomain"}, | |
"range": {"signal": "[0,ganttWidth]"} | |
}, | |
{ | |
"name": "scaleXScroll", | |
"type": "linear", | |
"clamp": true, | |
"domain": {"signal": "[0, 1]"}, | |
"range": {"signal": "scrollDomain"} | |
}, | |
{ | |
"name": "xScaleMiniMap", | |
"type": "time", | |
"domain": { | |
"signal": "[initialDomainCenter - xDomainBounds.max/2, initialDomainCenter + xDomainBounds.max/2]" | |
}, | |
"range": {"signal": "[0, ganttWidth-122]"} | |
} | |
], | |
"axes": [ | |
{ | |
"description": "Bottom date axis", | |
"ticks": true, | |
"labelPadding": {"signal": "xCurrentDateFormat === '%B %Y' ? 2 :-12"}, | |
"scale": "x", | |
"position": {"signal": "columnsWidth"}, | |
"orient": "top", | |
"domainColor": "#CCC", | |
"domainWidth": 0.25, | |
"tickSize": 15, | |
"tickOpacity": 1, | |
"grid": true, | |
"zindex": -1, | |
"labelOverlap": true, | |
"formatType": "time", | |
"labelBound": true, | |
"tickCount": { | |
"signal": "xCurrentUnit === 'hour' ? 24*(span(xDomain)/86400000) : xCurrentUnit" | |
}, | |
"format": {"signal": "xCurrentDateFormat"}, | |
"labelSeparation": 3, | |
"tickExtra": true, | |
"encode": { | |
"labels": { | |
"update": { | |
"dx": {"signal": "xCurrentDateLabelDX"}, | |
"text": { | |
"signal": "xCurrentDateFormat === '%B %Y' ? split(datum.label, ' ') : datum.label" | |
} | |
} | |
}, | |
"ticks": { | |
"update": { | |
"stroke": {"value": "#CCC"}, | |
"strokeWidth": { | |
"signal": "xCurrentUnit === 'day' && datum.label === '01' ? 0 : indexof(datum.label, 'Jan') >= 0 ? 0 : 0.35" | |
} | |
} | |
}, | |
"grid": { | |
"update": { | |
"stroke": {"value": "#CCC"}, | |
"strokeWidth": { | |
"signal": "xCurrentUnit === 'day' && datum.label === '01' ? 0 : indexof(datum.label, 'Jan') >= 0 ? 0 : 0.35" | |
} | |
} | |
} | |
} | |
}, | |
{ | |
"description": "Top date axis", | |
"title": { | |
"signal": "xCurrentDateFormatOffset === '%B %Y' && (toDate(utcFormat((xDomain[0] + (xDomain[1]-xDomain[0])/2), '01-%B-%Y')) < domain('x')[0]) ? utcFormat((xDomain[0] + (xDomain[1]-xDomain[0])/2), '%B %Y') : null" | |
}, | |
"titleX": {"signal": "ganttWidth/2"}, | |
"titleY": -25, | |
"titleBaseline": {"value": "middle"}, | |
"titleFontSize": {"value": 10}, | |
"titleFontWeight": "400", | |
"scale": "x", | |
"position": {"signal": "columnsWidth"}, | |
"domain": false, | |
"orient": "top", | |
"offset": 0, | |
"tickSize": 15, | |
"tickOpacity": 1, | |
"tickWidth": 0.5, | |
"tickColor": "#666", | |
"labelBaseline": "bottom", | |
"grid": true, | |
"gridWidth": 0.5, | |
"gridColor": {"value": "#666"}, | |
"zindex": 1, | |
"labelPadding": 5, | |
"labelOverlap": true, | |
"formatType": "time", | |
"labelBound": true, | |
"tickCount": {"signal": "(xCurrentUnitOffset || 0)"}, | |
"format": {"signal": "xCurrentDateFormatOffset"}, | |
"labelSeparation": 5, | |
"encode": { | |
"labels": { | |
"update": { | |
"text": { | |
"signal": "xCurrentDateFormat === '%B %Y' ? null : datum.label" | |
}, | |
"x": { | |
"signal": "xCurrentDateFormatOffset === '%Y' ? toDate(utcFormat(datum.value, '01-Jun-%Y')) > xDomain[1] ? scale('x', datum.value)+(scale('x', xDomain[1])-scale('x', datum.value))/2 : scale('x', toDate(utcFormat(datum.value, '01-Jun-%Y'))) : xCurrentDateFormatOffset === '%B %Y' ? toDate(utcFormat(datum.value, '17-%b-%Y')) > xDomain[1] ? scale('x', datum.value)+(scale('x', xDomain[1])-scale('x', datum.value))/2 : scale('x', toDate(utcFormat(datum.value, '15-%b-%Y'))) : scale('x', datum.value)" | |
}, | |
"dx": { | |
"signal": "xCurrentDateFormatOffset === '%Y' || xCurrentDateFormatOffset === '%B %Y' ? 0 : xCurrentDateOffsetLabelDX" | |
}, | |
"align": {"value": "center"} | |
} | |
} | |
} | |
} | |
], | |
"data": [ | |
{ | |
"name": "configurations", | |
"values": [{"label": null, "value": null}], | |
"transform": [ | |
{ | |
"type": "formula", | |
"expr": "['Configurations (for testing purposes only): ', '• Desired Canvas Width: ' + desiredWidth + 'px', '• Columns Percent of Width: ' + format(columnsWidthPercent, '.0%'), '• Initial Date Unit Offset: ' + offsetUnit, '• Initial Date Domain: ' + utcFormat(xDomainInitial[0], '%d-%b-%y %H:%M') + ' - ' + utcFormat(xDomainInitial[1], '%d-%b-%y %H:%M'), '• Record Count in Dataset: ' + recordCount, '• Block Height: ' + blockHeight]", | |
"as": "label" | |
}, | |
{"type": "flatten", "fields": ["label"]}, | |
{"type": "formula", "expr": "split(datum.label, ': ')", "as": "label"}, | |
{ | |
"type": "formula", | |
"expr": "trim(datum.label[1]) === '' ? null : trim(datum.label[1])", | |
"as": "value" | |
}, | |
{"type": "formula", "expr": "datum.label[0]+':'", "as": "label"}, | |
{"type": "window", "ops": ["row_number"], "as": ["index"]} | |
] | |
}, | |
{ | |
"name": "properties", | |
"values": [{"label": null, "value": null}], | |
"transform": [ | |
{ | |
"type": "formula", | |
"expr": "['Properties (for testing purposes only): ', '• Current Domain: '+utcFormat(xDomain[0], '%d-%b-%y %H:%M') + ' - ' + utcFormat(xDomain[1], '%d-%b-%y %H:%M'), '• Current Date Unit: '+xCurrentUnit, '• Current Domain Span: '+ format(span(xDomain)/scale('dateUnitIncrementMS', replace(xCurrentUnit, 'hour', 'hours')), '.2f') + ' ' + xCurrentUnit+('s'), '• Current Domain Percentage: '+format(span(xDomain)/(xDomainBounds.max-xDomainBounds.min), '.1%')]", | |
"as": "label" | |
}, | |
{"type": "flatten", "fields": ["label"]}, | |
{"type": "formula", "expr": "split(datum.label, ': ')", "as": "label"}, | |
{ | |
"type": "formula", | |
"expr": "trim(datum.label[1]) === '' ? null : trim(datum.label[1])", | |
"as": "value" | |
}, | |
{"type": "formula", "expr": "datum.label[0]+':'", "as": "label"}, | |
{"type": "window", "ops": ["row_number"], "as": ["index"]} | |
] | |
}, | |
{ | |
"name": "dataset", | |
"values": [{"startDate": null}], | |
"transform": [ | |
{"type": "formula", "expr": "offsetUnit", "as": "offsetUnit"}, | |
{ | |
"type": "formula", | |
"expr": "negativeDateOffsetFromToday", | |
"as": "negativeDateOffsetFromToday" | |
}, | |
{ | |
"type": "formula", | |
"expr": "positiveOffsetFromToday", | |
"as": "positiveOffsetFromToday" | |
}, | |
{"type": "formula", "expr": "recordCount", "as": "recordCount"}, | |
{"type": "formula", "expr": "todayDate", "as": "startDate"}, | |
{ | |
"type": "formula", | |
"expr": "timeOffset(datum.offsetUnit, datum.startDate, datum.negativeDateOffsetFromToday)", | |
"as": "startDate" | |
}, | |
{ | |
"type": "formula", | |
"expr": "timeOffset(datum.offsetUnit, todayDate, datum.positiveOffsetFromToday)", | |
"as": "endDate" | |
}, | |
{ | |
"type": "formula", | |
"expr": "(datum.endDate-datum.startDate)/datum.recordCount", | |
"as": "recordIncrement" | |
}, | |
{ | |
"type": "formula", | |
"expr": "sequence(+datum.startDate+datum.recordIncrement/2, +datum.endDate+datum.recordIncrement, datum.recordIncrement/2)", | |
"as": "endDate" | |
}, | |
{"type": "flatten", "fields": ["endDate"], "as": ["endDate"]}, | |
{"type": "formula", "expr": "+datum.startDate", "as": "startDate"}, | |
{"type": "window", "ops": ["row_number"], "as": ["index"]}, | |
{ | |
"type": "formula", | |
"expr": "datum.endDate<todayDate ? null : datum.endDate-todayDate", | |
"as": "afterTodayDuration" | |
}, | |
{ | |
"type": "window", | |
"ops": ["sum"], | |
"fields": ["afterTodayDuration"], | |
"as": ["aggAfterTodayDuration"] | |
}, | |
{ | |
"type": "formula", | |
"expr": "datum.afterTodayDuration === datum.aggAfterTodayDuration ? datum.startDate : (random()*(datum.endDate-datum.startDate))+datum.startDate", | |
"as": "startDate" | |
}, | |
{ | |
"type": "formula", | |
"expr": "utcFormat(datum.startDate, '%Y-%m-%dT%H:%M:%S.%LZ')", | |
"as": "startDateFormatted" | |
}, | |
{ | |
"type": "formula", | |
"expr": "utcFormat(datum.endDate, '%Y-%m-%dT%H:%M:%S.%LZ')", | |
"as": "endDateFormatted" | |
}, | |
{ | |
"type": "formula", | |
"expr": "datum.startDate+' '+datum.endDate", | |
"as": "sort" | |
}, | |
{"type": "collect", "sort": {"field": "sort", "order": "ascending"}} | |
] | |
}, | |
{ | |
"name": "xDomainInitial", | |
"source": "dataset", | |
"transform": [ | |
{ | |
"type": "aggregate", | |
"fields": ["startDate", "endDate"], | |
"ops": ["min", "max"], | |
"as": ["minDate", "maxDate"] | |
}, | |
{ | |
"type": "formula", | |
"expr": "[datum.minDate-scale('dateUnitIncrementMS', 'hours'),datum.maxDate+scale('dateUnitIncrementMS', 'hours')]", | |
"as": "domain" | |
}, | |
{ | |
"type": "formula", | |
"expr": "[utcFormat(datum.domain[0], '%d-%b-%Y %H:%M:%S.%LZ'), utcFormat(datum.domain[1], '%d-%b-%Y %H:%M:%S.%LZ')]", | |
"as": "domainFormatted" | |
}, | |
{ | |
"type": "formula", | |
"expr": "[datum.minDate-scale('dateUnitIncrementMS', 'hours'), datum.minDate + ((ganttWidth-minDateBandwidth)/minDateBandwidth)*scale('dateUnitIncrementMS', 'hours')]", | |
"as": "hourDomain" | |
}, | |
{ | |
"type": "formula", | |
"expr": "[datum.minDate-scale('dateUnitIncrementMS', 'day'), datum.minDate + ((ganttWidth-minDateBandwidth)/minDateBandwidth)*scale('dateUnitIncrementMS', 'day')]", | |
"as": "dayDomain" | |
}, | |
{ | |
"type": "formula", | |
"expr": "ceil(span(datum.domain)/scale('dateUnitIncrementMS', 'year'))", | |
"as": "yearCount" | |
} | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment