Template:Graph:US Map state highlight

From Bonkipedia
Revision as of 20:27, 9 June 2017 by [[mw:]]>Yurik
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Template documentation


This graph's main version resides at Template:Graph:US Map state highlight. Please make or suggest all the changes there, and copy it everywhere else (until the copying is automated)

{{Graph:US Map state highlight

| table=Bea.gov/GDP by state.tab
| title=Gross Domestic Product by State
}}

<graph mode="interactive">

{

 //
 // ATTENTION: This code is maintained at https://www.mediawiki.org/wiki/Template:Graph:US_Map_state_highlight
 //            Please do not modify it anywhere else, as it may get copied and override your changes.
 //            Suggestions can be made at https://www.mediawiki.org/wiki/Template_talk:Graph:US_Map_state_highlight
 //
 "version": 2,
 "width": 300,
 "height": 265,
 "signals": [
   // TODO: should be last available
   { "name": "initYear", "init": 2016 },
   { "name": "gapHeight", "init": 26 },
   {
     // Hide overview if total height is too small
     "name": "showOverview",
     "init": {"expr": "true || height < (gapHeight + 100)" }
   },
   { "name": "overviewHeight", "init": {"expr": "showOverview ? 40 : 0" } },
   { "name": "detailHeight", "init": {"expr": "height - (showOverview ? overviewHeight + gapHeight : 0)" } },
   { "name": "overviewYPos", "init": {"expr": "height - overviewHeight" } },
   {
     "name": "brush_start",
     "streams": [{
       "type": "@overview:mousedown, @overview:touchstart", 
       "expr": "clamp(eventX(), 0, width)",
       "scale": {"name": "xOverview", "invert": true}
     }]
   },
   {
     "name": "brush_end",
     "streams": [{
       "type": "@overview:mousedown, [@overview:mousedown, window:mouseup] > window:mousemove, @overview:mouseup, @overview:touchstart, [@overview:touchstart, window:touchend] > window:touchmove, @overview:touchend",
       "expr": "clamp(eventX(), 0, width)",
       "scale": {"name": "xOverview", "invert": true}
     }]
   },
   {
     "name": "fromYear", 
     "init": {"expr": "initYear"},
     "expr": "year(min(brush_start, brush_end))"
   },
   {
     "name": "toYear",
     "init": {"expr": "initYear"},
     "expr": "year(max(brush_start, brush_end))"
   },
   {
     "name": "isRange", 
     "init": {"expr": "false"},
     "expr": "fromYear !== toYear"
   },
   {
     "name": "tooltip",
     "init": {"expr": "{x: 0, y: 0, datum: false }"}, 
     "streams": [
       {"type": "@map:mouseout, @map:touchstart", "expr": "{x: 0, y: 0, datum: false }" },
       {"type": "@map:mouseover, @map:touchstart", "expr": "{x: eventX(), y: eventY(), datum: eventItem().datum.lookup}" }
     ]
   },
 ],
 "data": [{
   "name": "data",
   "url": "tabular:///Bea.gov/GDP by state.tab",
   "format": {"type": "json", "property": "data"},
 },{
   "name": "totals",
   "source": "data",
   "transform": [
     { "type": "formula", "field": "date", "expr": "datetime(datum.year, 0, 1)" },
     // TODO: We shouldn't list each field this way... nasty
     { "type": "formula", "field": "total", "expr": "datum.AL+datum.AK+datum.AZ+datum.AR+datum.CA+datum.CO+datum.CT+datum.DE+datum.DC+datum.FL+datum.GA+datum.HI+datum.ID+datum.IL+datum.IN+datum.IA+datum.KS+datum.KY+datum.LA+datum.ME+datum.MD+datum.MA+datum.MI+datum.MN+datum.MS+datum.MO+datum.MT+datum.NE+datum.NV+datum.NH+datum.NJ+datum.NM+datum.NY+datum.NC+datum.ND+datum.OH+datum.OK+datum.OR+datum.PA+datum.RI+datum.SC+datum.SD+datum.TN+datum.TX+datum.UT+datum.VT+datum.VA+datum.WA+datum.WV+datum.WI+datum.WY" },
   ]
 },{
   // Select just the source data for the starting year
   "name": "firstYearData",
   "source": "data",
   "transform": [{
     "type": "filter", "test": "datum.year === fromYear"
   },{
     // TODO: autogenerate this list
     "type": "fold",
     "fields": ["AL","AK","AZ","AR","CA","CO","CT","DE","DC","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]
   }]
 },{
   // Select just the source data for the ending year
   "name": "yearData",
   "source": "data",
   "transform": [{
     "type": "filter", "test": "datum.year === toYear"
   },{
     "type": "fold",
     // TODO: autogenerate this list
     "fields": ["AL","AK","AZ","AR","CA","CO","CT","DE","DC","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]
   },{
     "type": "lookup",
     "on": "firstYearData",
     "onKey": "key",
     "keys": ["key"],
     "as": ["firstYear"],
     "default": null
   },{
     "type": "formula", "field": "calc", "expr": "if(isRange, (datum.value - datum.firstYear.value)/datum.firstYear.value, datum.value)"
   }]
 },{
   "name": "mapData",
   "url": "map:///Naturalearthdata.com/US_states.map",
   "format": {"type": "json", "property": "data.features"},
   "transform": [{
     "type": "geopath",
     "projection": "albersUsa",
     "scale": 500,
     "translate": [200, 100]
   },{
     "type": "lookup",
     "on": "yearData",
     "onKey": "key",
     "keys": ["id"],
     "as": ["lookup"],
     "default": null
   }]
 },{
   "name": "dummyValue",
   "values": [{}]
 }],
 "scales": [{
   "name": "color",
   "type": "linear",
   "domain": {"data": "yearData", "field": "calc"},
   "range": ["#f1f1f0", "#08306b"],
   "zero": false
 },{
   "name": "diffColor",
   "type": "linear",
   "domain": [-1, -0.8, -0.6, -0.3, -0.1, 0, 0.1, 0.3, 0.6, 0.8, 1],
   "range": ["#313695", "#4575b4", "#74add1", "#abd9e9", "#e0f3f8", "#ffffbf", "#fee090", "#fdae61", "#f46d43", "#d73027", "#a50026"],
   "zero": false
 },{
     "name": "xOverview",
     "type": "time",
     "range": "width",
     "domain": {"data": "totals", "field": "date"}
 },{
     "name": "yOverview",
     "type": "linear",
     "rangeMin": {"signal": "overviewHeight"},
     "nice": true,
     "zero": false,
     "domain": {"data": "totals", "field": "total"}
 }],
 "marks": [{
   "type": "group",
   "name": "detail",
   "properties": {
     "enter": {
       "height": {"signal": "detailHeight"},
       "width": {"signal": "width"}
   } },
   "marks": [{
     "name": "map",
     "type": "path",
     "from": {"data": "mapData"},
     "properties": {
       "enter": {
         "stroke": {"value": "#fff"},
         "path": {"field": "layout_path"},
       },
       "update": {
         "fill": [
           {"test": "isRange", "field": "lookup.calc", "scale": "diffColor"},
           {"field": "lookup.calc", "scale": "color"}
   ]} } }]
 },{
   "type": "group",
   "name": "overview",
   "from": {
     "data": "dummyValue",
     // HACK: brush_end is needed to fool optimizer, because otherwise legend doesn't auto-update
     "transform": [{"type": "filter", "test": "(brush_end && 0) || showOverview"}]
   },
   "properties": {
     "enter": {
       "x": {"value": 0},
       "y": {"signal": "overviewYPos"},
       "height": {"signal": "overviewHeight"},
       "width": {"signal": "width"},
       "fill": {"value": "transparent"}
   } },
   "axes": [
     {"type": "x", "scale": "xOverview"}
   ],
   "marks": [{
     // Draw scale for a single year (I wish we could dynamically pick which scale to use for the legend)
     "type": "group",
     // HACK: brush_end is needed to fool optimizer, because otherwise legend doesn't auto-update
     "from": { "data": "dummyValue", "transform": [{"type": "filter", "test": "(brush_end && 0) || !isRange"}] },
     "properties": { "enter": { "width": {"signal": "width"} } },
       "legends": [{
         "fill": "color",
         "offset": 20,
         "properties": {"legend": {"y": {"value": 30} } }
   }]},{
     // Draw scale for a range (I wish we could dynamically pick which scale to use for the legend)
     "type": "group",
     "from": { "data": "dummyValue", "transform": [{"type": "filter", "test": "isRange"}] },
     "properties": { "enter": { "width": {"signal": "width"} } },
       "legends": [{
         "fill": "diffColor",
         "offset": 20,
         "properties": {
           "legend": {"y": {"value": 30} },
           "labels": {
             "text": [
               {"test": "datum.data===0", "value": "0"},
               {"test": "(datum.data%1)===0", "template": "\u007b{datum.data|number:'.0%'}\u007d"},
               {"value": ""}
   ]} } }]},{
     "name": "yearLabel",
     "type": "text",
     "from": {
       "data": "dummyValue",
       "transform": [
         {"type": "formula", "field": "text", "expr": "if(isRange,fromYear + '-' + toYear, fromYear)"},
         {"type": "formula", "field": "fontSize", "expr": "if(isRange,22,32)"},
     ]},
     "properties": {
       "enter": {
         "x": {"signal": "width", "offset": 72},
         "y": {"value": 20},
         "fontWeight": {"value": "bold"},
         "align": {"value": "center"},
         "baseline": {"value": "middle"},
         "fill": {"value": "#08306b"}
       },
       "update": {
         "fontSize": {"field": "fontSize"},
          "text": {"field": "text"}
   } } },{
     "type": "line",
     "from": { "data": "totals" },
     "properties": {
       "update": {
         "x": {"scale": "xOverview", "field": "date"},
         "y": {"scale": "yOverview", "field": "total"},
         "stroke": {"value": "#08306b"},
         "strokeWidth": {"value": 2}
   } } },{
     "type": "rect",
     "from": {
       "data": "dummyValue",
       "transform": [
         {"type": "formula", "field": "fromDate", "expr": "datetime(fromYear, -6, 1)"},
         {"type": "formula", "field": "toDate", "expr": "datetime(toYear, 6, 1)"},
     ]},
     "properties": {
       "enter": {
         "y": {"value": 0},
         "height": {"signal": "overviewHeight"},
         "fill": {"value": "#333"},
         "fillOpacity": {"value": 0.2},
         "stroke": {"value": "#f00"},
         "strokeDash": {"value": [4]},
       },
       "update": {
         "x": {"scale": "xOverview", "field": "fromDate"},
         "x2": {"scale": "xOverview", "field": "toDate"}
 } } }]},
 
 {
   "name": "tooltip",
     "type": "group",
     "from": {
       "data": "dummyValue",
       "transform": [
         {"type": "filter", "test": "tooltip.datum && tooltip.datum.calc"},
         {"type": "formula", "field": "offsetX", "expr": "5"},
         {"type": "formula", "field": "offsetY", "expr": "30"},
         {"type": "formula", "field": "tipWidth", "expr": "200"},
         {"type": "formula", "field": "tipHeight", "expr": "51"},
         {"type": "formula", "field": "alignLeft", "expr": "tooltip.x > width - datum.offsetX - datum.tipWidth"},
         {"type": "formula", "field": "alignTop", "expr": "tooltip.y > height - datum.offsetY - datum.tipHeight"},
         {"type": "formula", "field": "x", "expr": "max(0, tooltip.x + (datum.alignLeft ? -datum.offsetX-datum.tipWidth : datum.offsetX ))"},
         {"type": "formula", "field": "y", "expr": "tooltip.y + (datum.alignTop ? -1 : 1) * datum.offsetY"},
         {"type": "formula", "field": "lookupYear", "expr": "datetime(fromYear, 0, 1)"},
     {
     "type": "lookup",
     "on": "totals",
     "onKey": "lookupYear",
     "keys": ["date"],
     "as": ["totals"],
     "default": null
     },
         {"type": "formula", "field": "relGrowth", "expr": "tooltip.datum.calc/datum.totals.total"},
     ]},
     "properties": {
       "update": {
         "x": {"field": "x" }, "y": {"field": "y" },
         "width": {"field": "tipWidth" },
         "height": {"field": "tipHeight" },
         "fill": {"value": "#fff"},
         "fillOpacity": {"value": 0.85},
         "stroke": {"value": "#aaa"},
         "strokeWidth": {"value": 0.5}
     } },
     "marks": [
       {
         "type": "text",
         "properties": {
           "update": {
             "x": {"value": 6}, "y": {"value": 14},
             "text": {"template": "\u007b{tooltip.datum.key}\u007d"},
             "fill": {"value": "black"},
             "fontWeight": {"value": "bold"}
       } } },
       {
         "type": "text",
         "properties": {
           "update": {
             "x": {"value": 6}, "y": {"value": 29},
             "text": [
               {"test": "isRange", "template": "Growth:\t\u007b{tooltip.datum.calc|number:'.1%'}\u007d"},
               {"template": "State GDP:\t\u007b{tooltip.datum.calc|number:',.0f'}\u007d"},
             ],
             "fill": {"value": "black"},
       } } },
       {
         "type": "text",
         "properties": {
           "update": {
             "x": {"value": 6}, "y": {"value": 44},
             "text": [
               {"test": "isRange", "template": ""},
               {"template": "Percent of total:\t\u007b{parent.relGrowth|number:'.1%'}\u007d"},
             ],
             "fill": {"value": "black"},
       } } },
   ]}

// Draw title at the top of the graph , {

     "type": "text",
     "properties": {
       "enter": {
         "x": {"signal": "width", "mult": 0.5, "offset": 30},
         "y": {"value": -15},
         "text": {"value": "Gross Domestic Product by State"},
         "fontWeight": {"value": "bold"},
         "align": {"value": "center"},
         "baseline": {"value": "bottom"},
         "fill": {"value": "#000"}
       }
     }
   }
 ]

} </graph> See or edit source data.

<graph>
{
  //
  // ATTENTION: This code is maintained at https://www.mediawiki.org/wiki/Template:Graph:US_Map_state_highlight
  //            Please do not modify it anywhere else, as it may get copied and override your changes.
  //            Suggestions can be made at https://www.mediawiki.org/wiki/Template_talk:Graph:US_Map_state_highlight
  //

  "version": 2,
  "width": 300,
  "height": 265,
  "signals": [
    // TODO: should be last available
    { "name": "initYear", "init": 2016 },
    { "name": "gapHeight", "init": 26 },
    {
      // Hide overview if total height is too small
      "name": "showOverview",
      "init": {"expr": "true || height < (gapHeight + 100)" }
    },
    { "name": "overviewHeight", "init": {"expr": "showOverview ? 40 : 0" } },
    { "name": "detailHeight", "init": {"expr": "height - (showOverview ? overviewHeight + gapHeight : 0)" } },
    { "name": "overviewYPos", "init": {"expr": "height - overviewHeight" } },
    {
      "name": "brush_start",
      "streams": [{
        "type": "@overview:mousedown, @overview:touchstart", 
        "expr": "clamp(eventX(), 0, width)",
        "scale": {"name": "xOverview", "invert": true}
      }]
    },
    {
      "name": "brush_end",
      "streams": [{
        "type": "@overview:mousedown, [@overview:mousedown, window:mouseup] > window:mousemove, @overview:mouseup, @overview:touchstart, [@overview:touchstart, window:touchend] > window:touchmove, @overview:touchend",
        "expr": "clamp(eventX(), 0, width)",
        "scale": {"name": "xOverview", "invert": true}
      }]
    },
    {
      "name": "fromYear", 
      "init": {"expr": "initYear"},
      "expr": "year(min(brush_start, brush_end))"
    },
    {
      "name": "toYear",
      "init": {"expr": "initYear"},
      "expr": "year(max(brush_start, brush_end))"
    },
    {
      "name": "isRange", 
      "init": {"expr": "false"},
      "expr": "fromYear !== toYear"
    },
    {
      "name": "tooltip",
      "init": {"expr": "{x: 0, y: 0, datum: false }"}, 
      "streams": [
        {"type": "@map:mouseout, @map:touchstart", "expr": "{x: 0, y: 0, datum: false }" },
        {"type": "@map:mouseover, @map:touchstart", "expr": "{x: eventX(), y: eventY(), datum: eventItem().datum.lookup}" }
      ]
    },
  ],
  "data": [{
    "name": "data",
    "url": "tabular:///{{{table}}}",
    "format": {"type": "json", "property": "data"},
  },{
    "name": "totals",
    "source": "data",
    "transform": [
      { "type": "formula", "field": "date", "expr": "datetime(datum.year, 0, 1)" },
      // TODO: We shouldn't list each field this way... nasty
      { "type": "formula", "field": "total", "expr": "datum.AL+datum.AK+datum.AZ+datum.AR+datum.CA+datum.CO+datum.CT+datum.DE+datum.DC+datum.FL+datum.GA+datum.HI+datum.ID+datum.IL+datum.IN+datum.IA+datum.KS+datum.KY+datum.LA+datum.ME+datum.MD+datum.MA+datum.MI+datum.MN+datum.MS+datum.MO+datum.MT+datum.NE+datum.NV+datum.NH+datum.NJ+datum.NM+datum.NY+datum.NC+datum.ND+datum.OH+datum.OK+datum.OR+datum.PA+datum.RI+datum.SC+datum.SD+datum.TN+datum.TX+datum.UT+datum.VT+datum.VA+datum.WA+datum.WV+datum.WI+datum.WY" },
    ]
  },{
    // Select just the source data for the starting year
    "name": "firstYearData",
    "source": "data",
    "transform": [{
      "type": "filter", "test": "datum.year === fromYear"
    },{
      // TODO: autogenerate this list
      "type": "fold",
      "fields": ["AL","AK","AZ","AR","CA","CO","CT","DE","DC","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]
    }]
  },{
    // Select just the source data for the ending year
    "name": "yearData",
    "source": "data",
    "transform": [{
      "type": "filter", "test": "datum.year === toYear"
    },{
      "type": "fold",
      // TODO: autogenerate this list
      "fields": ["AL","AK","AZ","AR","CA","CO","CT","DE","DC","FL","GA","HI","ID","IL","IN","IA","KS","KY","LA","ME","MD","MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ","NM","NY","NC","ND","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VT","VA","WA","WV","WI","WY"]
    },{
      "type": "lookup",
      "on": "firstYearData",
      "onKey": "key",
      "keys": ["key"],
      "as": ["firstYear"],
      "default": null
    },{
      "type": "formula", "field": "calc", "expr": "if(isRange, (datum.value - datum.firstYear.value)/datum.firstYear.value, datum.value)"
    }]
  },{
    "name": "mapData",
    "url": "map:///Naturalearthdata.com/US_states.map",
    "format": {"type": "json", "property": "data.features"},
    "transform": [{
      "type": "geopath",
      "projection": "albersUsa",
      "scale": 500,
      "translate": [200, 100]
    },{
      "type": "lookup",
      "on": "yearData",
      "onKey": "key",
      "keys": ["id"],
      "as": ["lookup"],
      "default": null
    }]
  },{
    "name": "dummyValue",
    "values": [{}]
  }],
  "scales": [{
    "name": "color",
    "type": "linear",
    "domain": {"data": "yearData", "field": "calc"},
    "range": ["#f1f1f0", "#08306b"],
    "zero": false
  },{
    "name": "diffColor",
    "type": "linear",
    "domain": [-1, -0.8, -0.6, -0.3, -0.1, 0, 0.1, 0.3, 0.6, 0.8, 1],
    "range": ["#313695", "#4575b4", "#74add1", "#abd9e9", "#e0f3f8", "#ffffbf", "#fee090", "#fdae61", "#f46d43", "#d73027", "#a50026"],
    "zero": false
  },{
      "name": "xOverview",
      "type": "time",
      "range": "width",
      "domain": {"data": "totals", "field": "date"}
  },{
      "name": "yOverview",
      "type": "linear",
      "rangeMin": {"signal": "overviewHeight"},
      "nice": true,
      "zero": false,
      "domain": {"data": "totals", "field": "total"}
  }],
  "marks": [{
    "type": "group",
    "name": "detail",
    "properties": {
      "enter": {
        "height": {"signal": "detailHeight"},
        "width": {"signal": "width"}
    } },
    "marks": [{
      "name": "map",
      "type": "path",
      "from": {"data": "mapData"},
      "properties": {
        "enter": {
          "stroke": {"value": "#fff"},
          "path": {"field": "layout_path"},
        },
        "update": {
          "fill": [
            {"test": "isRange", "field": "lookup.calc", "scale": "diffColor"},
            {"field": "lookup.calc", "scale": "color"}
    ]} } }]
  },{
    "type": "group",
    "name": "overview",
    "from": {
      "data": "dummyValue",
      // HACK: brush_end is needed to fool optimizer, because otherwise legend doesn't auto-update
      "transform": [{"type": "filter", "test": "(brush_end && 0) || showOverview"}]
    },
    "properties": {
      "enter": {
        "x": {"value": 0},
        "y": {"signal": "overviewYPos"},
        "height": {"signal": "overviewHeight"},
        "width": {"signal": "width"},
        "fill": {"value": "transparent"}
    } },
    "axes": [
      {"type": "x", "scale": "xOverview"}
    ],
    "marks": [{
      // Draw scale for a single year (I wish we could dynamically pick which scale to use for the legend)
      "type": "group",
      // HACK: brush_end is needed to fool optimizer, because otherwise legend doesn't auto-update
      "from": { "data": "dummyValue", "transform": [{"type": "filter", "test": "(brush_end && 0) || !isRange"}] },
      "properties": { "enter": { "width": {"signal": "width"} } },
        "legends": [{
          "fill": "color",
          "offset": 20,
          "properties": {"legend": {"y": {"value": 30} } }
    }]},{
      // Draw scale for a range (I wish we could dynamically pick which scale to use for the legend)
      "type": "group",
      "from": { "data": "dummyValue", "transform": [{"type": "filter", "test": "isRange"}] },
      "properties": { "enter": { "width": {"signal": "width"} } },
        "legends": [{
          "fill": "diffColor",
          "offset": 20,
          "properties": {
            "legend": {"y": {"value": 30} },
            "labels": {
              "text": [
                {"test": "datum.data===0", "value": "0"},
                {"test": "(datum.data%1)===0", "template": "\u007b{datum.data|number:'.0%'}\u007d"},
                {"value": ""}
    ]} } }]},{
      "name": "yearLabel",
      "type": "text",
      "from": {
        "data": "dummyValue",
        "transform": [
          {"type": "formula", "field": "text", "expr": "if(isRange,fromYear + '-' + toYear, fromYear)"},
          {"type": "formula", "field": "fontSize", "expr": "if(isRange,22,32)"},
      ]},
      "properties": {
        "enter": {
          "x": {"signal": "width", "offset": 72},
          "y": {"value": 20},
          "fontWeight": {"value": "bold"},
          "align": {"value": "center"},
          "baseline": {"value": "middle"},
          "fill": {"value": "#08306b"}
        },
        "update": {
          "fontSize": {"field": "fontSize"},
           "text": {"field": "text"}
    } } },{
      "type": "line",
      "from": { "data": "totals" },
      "properties": {
        "update": {
          "x": {"scale": "xOverview", "field": "date"},
          "y": {"scale": "yOverview", "field": "total"},
          "stroke": {"value": "#08306b"},
          "strokeWidth": {"value": 2}
    } } },{
      "type": "rect",
      "from": {
        "data": "dummyValue",
        "transform": [
          {"type": "formula", "field": "fromDate", "expr": "datetime(fromYear, -6, 1)"},
          {"type": "formula", "field": "toDate", "expr": "datetime(toYear, 6, 1)"},
      ]},
      "properties": {
        "enter": {
          "y": {"value": 0},
          "height": {"signal": "overviewHeight"},
          "fill": {"value": "#333"},
          "fillOpacity": {"value": 0.2},
          "stroke": {"value": "#f00"},
          "strokeDash": {"value": [4]},
        },
        "update": {
          "x": {"scale": "xOverview", "field": "fromDate"},
          "x2": {"scale": "xOverview", "field": "toDate"}
  } } }]},
  
  {
    "name": "tooltip",
      "type": "group",
      "from": {
        "data": "dummyValue",
        "transform": [
          {"type": "filter", "test": "tooltip.datum && tooltip.datum.calc"},
          {"type": "formula", "field": "offsetX", "expr": "5"},
          {"type": "formula", "field": "offsetY", "expr": "30"},
          {"type": "formula", "field": "tipWidth", "expr": "200"},
          {"type": "formula", "field": "tipHeight", "expr": "51"},
          {"type": "formula", "field": "alignLeft", "expr": "tooltip.x > width - datum.offsetX - datum.tipWidth"},
          {"type": "formula", "field": "alignTop", "expr": "tooltip.y > height - datum.offsetY - datum.tipHeight"},
          {"type": "formula", "field": "x", "expr": "max(0, tooltip.x + (datum.alignLeft ? -datum.offsetX-datum.tipWidth : datum.offsetX ))"},
          {"type": "formula", "field": "y", "expr": "tooltip.y + (datum.alignTop ? -1 : 1) * datum.offsetY"},
          {"type": "formula", "field": "lookupYear", "expr": "datetime(fromYear, 0, 1)"},
      {
      "type": "lookup",
      "on": "totals",
      "onKey": "lookupYear",
      "keys": ["date"],
      "as": ["totals"],
      "default": null
      },
          {"type": "formula", "field": "relGrowth", "expr": "tooltip.datum.calc/datum.totals.total"},
      ]},
      "properties": {
        "update": {
          "x": {"field": "x" }, "y": {"field": "y" },
          "width": {"field": "tipWidth" },
          "height": {"field": "tipHeight" },
          "fill": {"value": "#fff"},
          "fillOpacity": {"value": 0.85},
          "stroke": {"value": "#aaa"},
          "strokeWidth": {"value": 0.5}
      } },

      "marks": [
        {
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6}, "y": {"value": 14},
              "text": {"template": "\u007b{tooltip.datum.key}\u007d"},
              "fill": {"value": "black"},
              "fontWeight": {"value": "bold"}
        } } },
        {
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6}, "y": {"value": 29},
              "text": [
                {"test": "isRange", "template": "Growth:\t\u007b{tooltip.datum.calc|number:'.1%'}\u007d"},
                {"template": "State GDP:\t\u007b{tooltip.datum.calc|number:',.0f'}\u007d"},
              ],
              "fill": {"value": "black"},
        } } },
        {
          "type": "text",
          "properties": {
            "update": {
              "x": {"value": 6}, "y": {"value": 44},
              "text": [
                {"test": "isRange", "template": ""},
                {"template": "Percent of total:\t\u007b{parent.relGrowth|number:'.1%'}\u007d"},
              ],
              "fill": {"value": "black"},
        } } },
    ]}

  ]
}
</graph>