Last active
          March 10, 2025 17:10 
        
      - 
      
- 
        Save Giammaria/830c975be22fc3871902ef653cc37233 to your computer and use it in GitHub Desktop. 
    20250308_numeric_bar_kpi_v_v1
  
        
  
    
      This file contains hidden or 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": 300, | |
| "autosize": {"type": "none"}, | |
| "signals": [ | |
| {"name": "title", "value": "Metric Name"}, | |
| {"name": "padding", "value": 0}, | |
| {"name": "height", "update": "width"}, | |
| { | |
| "name": "darkMode", | |
| "init": "true", | |
| "bind": {"name": "Dark Mode", "input": "checkbox"} | |
| }, | |
| {"name": "background", "update": "darkMode ? '#202020' : '#fff'"}, | |
| {"name": "value", "init": "200000000"}, | |
| {"name": "goal", "init": "250000000"}, | |
| { | |
| "name": "initializedTime", | |
| "init": "now()", | |
| "on": [{"events": {"signal": "darkMode"}, "update": "now()"}] | |
| }, | |
| {"name": "tickCount", "value": 20}, | |
| { | |
| "name": "transitionDuration", | |
| "init": "clamp((value/goal)*1500+250, 250, 3000)" | |
| }, | |
| { | |
| "name": "t", | |
| "init": "0", | |
| "on": [ | |
| { | |
| "events": {"type": "timer", "throttle": 10}, | |
| "update": "now() >= (initializedTime + transitionDuration) ? 1 : (now()-initializedTime)/(transitionDuration)" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "valueOpacity", | |
| "init": "0", | |
| "on": [ | |
| { | |
| "events": {"type": "timer", "throttle": 10}, | |
| "update": "clamp(now() < (initializedTime + transitionDuration) ? 0 : (now()-75-(initializedTime + transitionDuration))/(250), 0, 1)" | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "valueInterpolated", | |
| "update": "+format((t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1)*value, '.2f')" | |
| }, | |
| {"name": "radius", "update": "min(width, height)/2.1"}, | |
| {"name": "mainColor", "update": "darkMode ? '#8C9EFF' : '#2943D1'"}, | |
| {"name": "secondaryColor", "update": "darkMode ? '#ccc' : '#888'"}, | |
| {"name": "tiertiaryColor", "update": "'#FAFAFA'"}, | |
| {"name": "font", "value": "sans-serif"}, | |
| {"name": "due", "update": "now()+(2.628e+9)*(random()*10)"}, | |
| {"name": "remainingDays", "update": "round((due-now())/(8.64e+7))"}, | |
| { | |
| "name": "dueText", | |
| "update": "['Due ' + utcFormat(due, '%d-%b-%y'), '━━━', remainingDays + ' day' + (remainingDays > 1 ? 's' : '') + ' remain']" | |
| }, | |
| {"name": "xDomain", "update": "[0, goal*1.2]"} | |
| ], | |
| "scales": [ | |
| { | |
| "name": "xBandScale", | |
| "type": "band", | |
| "domain": {"data": "trackDataset", "field": "index", "sort": true}, | |
| "range": {"signal": "[0.05*width,0.95*width]"}, | |
| "paddingInner": 0.3 | |
| }, | |
| { | |
| "name": "xScale", | |
| "type": "linear", | |
| "zero": true, | |
| "clamp": true, | |
| "domain": {"signal": "xDomain"}, | |
| "range": {"signal": "range('xBandScale')"} | |
| } | |
| ], | |
| "marks": [ | |
| { | |
| "name": "metric-title-text", | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "text": {"signal": "title"}, | |
| "font": {"signal": "font"}, | |
| "fontWeight": {"value": 500}, | |
| "fontSize": {"signal": "min(width,height)/14"}, | |
| "x": {"signal": "width/2"}, | |
| "y": {"signal": "height/20"}, | |
| "fill": {"signal": "secondaryColor"}, | |
| "baseline": {"value": "top"}, | |
| "align": {"value": "center"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "track-group", | |
| "from": {"data": "trackDataset"}, | |
| "type": "group", | |
| "encode": { | |
| "update": { | |
| "x": {"scale": "xBandScale", "field": "index"}, | |
| "width": {"signal": "bandwidth('xBandScale')"}, | |
| "y": {"signal": "data('metric-title-text')[0].bounds.y2+height/12"}, | |
| "height": {"signal": "height/10"}, | |
| "fill": {"value": "transparent"}, | |
| "cornerRadius": {"signal": "0.005*min(width, height)"}, | |
| "stroke": {"signal": "mainColor"}, | |
| "strokeWidth": {"value": 1.5}, | |
| "strokeOpacity": {"field": "opacity"}, | |
| "clip": {"value": true} | |
| } | |
| }, | |
| "marks": [ | |
| { | |
| "name": "value-rect", | |
| "type": "rect", | |
| "encode": { | |
| "update": { | |
| "width": { | |
| "signal": "bandwidth('xBandScale')*parent.bandPercentage" | |
| }, | |
| "height": {"signal": "height"}, | |
| "fill": {"signal": "mainColor"}, | |
| "fillOpacity": {"signal": "parent.opacity"} | |
| } | |
| } | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "goal-indicator-top-text", | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "x": {"scale": "xScale", "signal": "goal"}, | |
| "y": {"signal": "data('track-group')[0].bounds.y1"}, | |
| "align": {"value": "center"}, | |
| "baseline": {"value": "bottom"}, | |
| "fontSize": {"signal": "data('trackDataset')[0].fontSize*0.5"}, | |
| "fill": {"signal": "secondaryColor"}, | |
| "font": {"value": "Zapf Dingbats"}, | |
| "text": {"value": "⮟"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "goal-indicator-bottom-text", | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "x": {"scale": "xScale", "signal": "goal"}, | |
| "y": {"signal": "data('track-group')[0].bounds.y2"}, | |
| "align": {"value": "center"}, | |
| "baseline": {"value": "top"}, | |
| "fontSize": {"signal": "data('trackDataset')[0].fontSize*0.5"}, | |
| "fill": {"signal": "secondaryColor"}, | |
| "font": {"value": "Zapf Dingbats"}, | |
| "text": {"value": "⮝"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "value-text-label", | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "x": {"signal": "range('xScale')[0]"}, | |
| "y": {"signal": "data('track-group')[0].bounds.y2"}, | |
| "dy": {"signal": "height/10"}, | |
| "text": {"signal": "'Total:'"}, | |
| "fontSize": {"signal": "data('trackDataset')[0].fontSize*0.5"}, | |
| "fontWeight": {"signal": "200"}, | |
| "fill": {"signal": "secondaryColor"}, | |
| "align": {"signal": "'left'"}, | |
| "baseline": {"value": "top"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "value-text", | |
| "from": {"data": "value-text-label"}, | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "x": {"signal": "width*0.565"}, | |
| "y": {"signal": "datum.bounds.y2"}, | |
| "dy": {"signal": "height/50"}, | |
| "text": {"signal": "data('trackDataset')[0].valueFormatted"}, | |
| "fontSize": {"signal": "data('trackDataset')[0].fontSize"}, | |
| "fontWeight": {"signal": "700"}, | |
| "fill": {"signal": "mainColor"}, | |
| "align": {"signal": "'right'"}, | |
| "baseline": {"value": "bottom"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "goal-text-label", | |
| "from": {"data": "value-text-label"}, | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "x": {"signal": "range('xScale')[0]"}, | |
| "y": {"signal": "datum.bounds.y2"}, | |
| "dy": {"signal": "height/15"}, | |
| "text": {"signal": "'Goal:'"}, | |
| "fontSize": {"signal": "data('trackDataset')[0].fontSize*0.5"}, | |
| "fontWeight": {"signal": "200"}, | |
| "fill": {"signal": "secondaryColor"}, | |
| "align": {"signal": "'left'"}, | |
| "baseline": {"value": "top"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "goal-text", | |
| "from": {"data": "goal-text-label"}, | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "x": {"signal": "data('value-text')[0].bounds.x2"}, | |
| "y": {"signal": "datum.bounds.y2"}, | |
| "dy": {"signal": "height/100"}, | |
| "text": {"signal": "data('trackDataset')[0].goalFormatted"}, | |
| "fontSize": {"signal": "data('trackDataset')[0].fontSize*0.75"}, | |
| "fontWeight": {"signal": "600"}, | |
| "fill": {"signal": "secondaryColor"}, | |
| "align": {"signal": "'right'"}, | |
| "baseline": {"value": "bottom"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "percentage-text", | |
| "from": {"data": "value-text-label"}, | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "x": {"signal": "range('xScale')[1]"}, | |
| "y": {"signal": "datum.bounds.y2"}, | |
| "dy": { | |
| "signal": "-(datum.bounds.y2 - data('goal-text')[0].bounds.y1)/2" | |
| }, | |
| "text": {"signal": "data('trackDataset')[0].percentageFormatted"}, | |
| "fontSize": {"signal": "data('trackDataset')[0].fontSize"}, | |
| "fontWeight": {"signal": "700"}, | |
| "fill": {"signal": "mainColor"}, | |
| "align": {"signal": "'right'"}, | |
| "baseline": {"value": "middle"} | |
| } | |
| } | |
| }, | |
| { | |
| "name": "link-group", | |
| "type": "group", | |
| "data": [ | |
| { | |
| "name": "edges", | |
| "values": [{"edge": 1}, {"edge": 2}], | |
| "transform": [ | |
| { | |
| "type": "formula", | |
| "expr": "length(format(value/goal, '.0%'))", | |
| "as": "percentageLength" | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "(datum.edge === 1 ? data('value-text')[0].bounds.x2 : data('goal-text')[0].bounds.x2)+width/50", | |
| "as": "sourceX" | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "datum.edge === 1 ? (data('value-text')[0].bounds.y1 + (data('value-text')[0].bounds.y2-data('value-text')[0].bounds.y1)/2) : (data('goal-text')[0].bounds.y1 + (data('goal-text')[0].bounds.y2-data('goal-text')[0].bounds.y1)/2)", | |
| "as": "sourceY" | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "data('percentage-text')[0].bounds.x1-datum.percentageLength*data('trackDataset')[0].fontSize/3.5", | |
| "as": "goalX" | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "data('percentage-text')[0].bounds.y1+(data('percentage-text')[0].bounds.y2-data('percentage-text')[0].bounds.y1)/2", | |
| "as": "goalY" | |
| }, | |
| { | |
| "type": "linkpath", | |
| "sourceX": "sourceX", | |
| "sourceY": "sourceY", | |
| "targetX": "goalX", | |
| "targetY": "goalY", | |
| "orient": "horizontal", | |
| "shape": "diagonal" | |
| } | |
| ] | |
| } | |
| ], | |
| "marks": [ | |
| { | |
| "type": "path", | |
| "from": {"data": "edges"}, | |
| "encode": { | |
| "update": { | |
| "stroke": {"signal": "secondaryColor"}, | |
| "strokeWidth": {"value": 2} | |
| }, | |
| "enter": {"path": {"field": "path"}} | |
| } | |
| } | |
| ] | |
| }, | |
| { | |
| "name": "metric-date-due", | |
| "from": {"data": "goal-text"}, | |
| "type": "text", | |
| "encode": { | |
| "update": { | |
| "text": {"signal": "dueText"}, | |
| "font": {"signal": "font"}, | |
| "fontWeight": {"value": 400}, | |
| "fontSize": {"signal": "height/20"}, | |
| "x": {"signal": "width/2"}, | |
| "y": {"signal": "datum.bounds.y2", "offset": {"signal": "height/20"}}, | |
| "fill": {"signal": "secondaryColor"}, | |
| "angle": {"field": "angle"}, | |
| "baseline": {"value": "top"}, | |
| "align": {"value": "center"} | |
| } | |
| } | |
| } | |
| ], | |
| "data": [ | |
| { | |
| "name": "trackDataset", | |
| "values": [{}], | |
| "transform": [ | |
| { | |
| "type": "formula", | |
| "expr": "sequence((xDomain[1]+1)/tickCount, xDomain[1]+1, (xDomain[1]+1)/tickCount)", | |
| "as": "endDomain" | |
| }, | |
| {"type": "flatten", "fields": ["endDomain"]}, | |
| { | |
| "type": "formula", | |
| "expr": "round(datum.endDomain)", | |
| "as": "endDomain" | |
| }, | |
| { | |
| "type": "window", | |
| "ops": ["lag"], | |
| "fields": ["endDomain"], | |
| "as": ["startDomain"] | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "datum.startDomain || 0", | |
| "as": "startDomain" | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "valueInterpolated >= datum.startDomain ? clamp((valueInterpolated-datum.startDomain)/(datum.endDomain-datum.startDomain), 0, 1) : 0", | |
| "as": "bandPercentage" | |
| }, | |
| {"type": "formula", "expr": "valueInterpolated", "as": "value"}, | |
| { | |
| "type": "formula", | |
| "expr": "format(datum.value, '$.2s')", | |
| "as": "valueFormatted" | |
| }, | |
| {"type": "formula", "expr": "goal", "as": "goal"}, | |
| { | |
| "type": "formula", | |
| "expr": "format(datum.goal, '$.2s')", | |
| "as": "goalFormatted" | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "format(datum.value/datum.goal, '.0%')", | |
| "as": "percentageFormatted" | |
| }, | |
| {"type": "formula", "expr": "(min(width,height))/10", "as": "fontSize"}, | |
| { | |
| "type": "window", | |
| "ops": ["row_number"], | |
| "sort": {"field": "startDomain", "order": "ascending"}, | |
| "as": ["index"] | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "inrange(datum.goal, [datum.startDomain, datum.endDomain]) ? datum.index : 0", | |
| "as": "opacity" | |
| }, | |
| { | |
| "type": "joinaggregate", | |
| "ops": ["max"], | |
| "fields": ["opacity"], | |
| "as": ["opacity"] | |
| }, | |
| { | |
| "type": "formula", | |
| "expr": "clamp(0.1+(datum.index/datum.opacity)*0.9, 0, 1)", | |
| "as": "opacity" | |
| } | |
| ] | |
| } | |
| ] | |
| } | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment