Extension:Graph/Interactive Graph Tutorial 2

In this tutorial we will create an interactive graph that will display historical fertility rates per country, with a slider to pick the year, and a map to show rate distribution around the world. The source code for this graph is here. You might also be interested in the complete Vega documentation.

In this tutorial, we continue from the first part of the tutorial.

Drawing a map with some useful data
Now that the slider is working, we can add a map and mix it with the highlighting data. The map is stored as a raw TopoJSON text in wiki markup here. Each country is tagged with a ISO-3 country code. For this example, we will use fertility data that is stored as a CSV text in wiki markup here, copied from WorldBank (license). The CSV contains "country", "id" columns, as well as years 1960..2013, each as a separate column.

 { "version": 2, "width": 500, "height": 260, "padding": 12, "background": "#edf1f7", "signals": [ {     "name": "isDragging", "init": false, "streams": [ {"type": "@handle:mousedown","expr": "true"}, {"type": "mouseup","expr": "false"} ]   },    {      "name": "scaledHandlePosition", "streams": [ {         "type": "mousemove[isDragging]", "expr": "eventX", "scale": {"name": "yearsScale","invert": true} }     ]    },    {      "name": "currentYear", "init": 2000, "expr": "clamp(parseInt(scaledHandlePosition),1960,2013)" } ],  "scales": [ {     "name": "yearsScale", "type": "linear", "zero": false, "domain": [1960,2013], "range": "width" },   {      "name": "color", "type": "linear", "domain": {"data": "highlights","field": "v"}, "zero": true, "range": ["#ffff65","#cb0000"] } ],  "data": [ {     "name": "highlights", "url": "https://www.mediawiki.org/w/index.php?title=Extension:Graph/Demo/RawData:FertilityByCountryHistoric-csv&action=raw", "format": {"type": "csv"}, "transform": [ {         "type": "formula", "field": "v", "expr": "parseFloat(datum[''+currentYear])" }     ]    },    {      "name": "countries", "url": "https://www.mediawiki.org/w/index.php?title=Extension:Graph/Demo/RawData:WorldMap-iso3-json&action=raw", "format": {"type": "topojson","feature": "countries"}, "transform": [ {         "type": "geopath", "value": "data", "scale": 80, "center": [-180,125], "translate": [0,0], "projection": "equirectangular" },       {          "type": "lookup", "keys": ["id"], "on": "highlights", "onKey": "id", "as": ["zipped"], "default": {"v": null} }     ]    }  ],  "marks": [ {     "name": "yearLabel", "type": "text", "properties": { "enter": { "x": {"value": 0}, "y": {"value": 25}, "fontSize": {"value": 32}, "fontWeight": {"value": "bold"}, "fill": {"value": "steelblue"} },       "update": {"text": {"signal": "currentYear"}} }   },    {      "name": "scrollLine", "type": "rule", "properties": { "enter": { "x": {"value": 0}, "y": {"value": 40}, "x2": {"value": 500}, "stroke": {"value": "#000"}, "strokeWidth": {"value": 2} }     }    },    {      "name": "handle", "type": "path", "properties": { "enter": { "y": {"value": 40}, "path": {"value": "m-5.5,-10l0,20l11.5,-10l-11.5,-10z"}, "stroke": {"value": "#880"}, "strokeWidth": {"value": 2.5} },       "update": { "x": {"scale": "yearsScale","signal": "currentYear"}, "fill": {"value": "#fff"} },       "hover": {"fill": {"value": "#f00"}} }   },    {      "name": "map", "type": "path", "from": {"data": "countries"}, "properties": { "enter": {"path": {"field": "layout_path"}}, "update": {"fill": {"scale": "color","field": "zipped.v"}}, "hover": {"fill": {"value": "#989898"}} }   }  ] }

Adding Legend
Graph will be more informative if the user sees how colors correspond to numbers. Unfortunatelly Legend placement is a bit broken at the moment and will need to be fixed in Vega, but it tends to work in non-map based graphs.

 { "version": 2, "width": 500, "height": 260, "padding": 12, "background": "#edf1f7", "signals": [ {     "name": "isDragging", "init": false, "streams": [ {"type": "@handle:mousedown","expr": "true"}, {"type": "mouseup","expr": "false"} ]   },    {      "name": "scaledHandlePosition", "streams": [ {         "type": "mousemove[isDragging]", "expr": "eventX", "scale": {"name": "yearsScale","invert": true} }     ]    },    {      "name": "currentYear", "init": 2000, "expr": "clamp(parseInt(scaledHandlePosition),1960,2013)" } ],  "scales": [ {     "name": "yearsScale", "type": "linear", "zero": false, "domain": [1960,2013], "range": "width" },   {      "name": "color", "type": "linear", "domain": {"data": "highlights","field": "v"}, "zero": true, "range": ["#ffff65","#cb0000"] } ],  "data": [ {     "name": "highlights", "url": "https://www.mediawiki.org/w/index.php?title=Extension:Graph/Demo/RawData:FertilityByCountryHistoric-csv&action=raw", "format": {"type": "csv"}, "transform": [ {         "type": "formula", "field": "v", "expr": "parseFloat(datum[''+currentYear])" }     ]    },    {      "name": "countries", "url": "https://www.mediawiki.org/w/index.php?title=Extension:Graph/Demo/RawData:WorldMap-iso3-json&action=raw", "format": {"type": "topojson","feature": "countries"}, "transform": [ {         "type": "geopath", "value": "data", "scale": 80, "center": [-180,125], "translate": [0,0], "projection": "equirectangular" },       {          "type": "lookup", "keys": ["id"], "on": "highlights", "onKey": "id", "as": ["zipped"], "default": {"v": null} }     ]    }  ],  "legends": [ {     "fill": "color", "title": "Fertility", "offset":-300, "properties": { "gradient": { "stroke": {"value": "transparent"} },       "title": { "fontSize": {"value": 14} },     }    }  ],  "marks": [ {     "name": "yearLabel", "type": "text", "properties": { "enter": { "x": {"value": 0}, "y": {"value": 25}, "fontSize": {"value": 32}, "fontWeight": {"value": "bold"}, "fill": {"value": "steelblue"} },       "update": {"text": {"signal": "currentYear"}} }   },    {      "name": "scrollLine", "type": "rule", "properties": { "enter": { "x": {"value": 0}, "y": {"value": 40}, "x2": {"value": 500}, "stroke": {"value": "#000"}, "strokeWidth": {"value": 2} }     }    },    {      "name": "handle", "type": "path", "properties": { "enter": { "y": {"value": 40}, "path": {"value": "m-5.5,-10l0,20l11.5,-10l-11.5,-10z"}, "stroke": {"value": "#880"}, "strokeWidth": {"value": 2.5} },       "update": { "x": {"scale": "yearsScale","signal": "currentYear"}, "fill": {"value": "#fff"} },       "hover": {"fill": {"value": "#f00"}} }   },    {      "name": "map", "type": "path", "from": {"data": "countries"}, "properties": { "enter": {"path": {"field": "layout_path"}}, "update": {"fill": {"scale": "color","field": "zipped.v"}}, "hover": {"fill": {"value": "#989898"}} }   }  ] }

Adding Some Statistics
The map mouseover event will cause the country and the associated rate show up in the right corner.

 { "version": 2, "width": 500, "height": 260, "padding": 12, "background": "#edf1f7", "predicates": [ {     "name": "isNotNull", "type": "!=", "operands": [{"value": null}, {"arg": "id"}] } ],  "signals": [ {     "name": "isDragging", "init": false, "streams": [ {"type": "@handle:mousedown","expr": "true"}, {"type": "mouseup","expr": "false"} ]   },    {      "name": "scaledHandlePosition", "streams": [ {         "type": "mousemove[isDragging]", "expr": "eventX", "scale": {"name": "yearsScale","invert": true} }     ]    },    {      "name": "currentYear", "init": 2000, "expr": "clamp(parseInt(scaledHandlePosition),1960,2013)" },   {      "name": "tooltipSignal", "init": {"expr": "{x: 0, y: 0, datum: {zipped:{} } }"}, "streams": [ {           "type": "@map:mouseover", "expr": "{x: eventX, y: eventY, datum: eventItem.datum}" },       {            "type": "@map:mouseout", "expr": "{x: 0, y: 0, datum: {zipped:{} } }" }     ]     }  ],  "data": [ {     "name": "highlights", "url": "https://www.mediawiki.org/w/index.php?title=Extension:Graph/Demo/RawData:FertilityByCountryHistoric-csv&action=raw", "format": {"type": "csv"}, "transform": [ {         "type": "formula", "field": "v", "expr": "parseFloat(datum[''+currentYear])" }     ]    },    {      "name": "countries", "url": "https://www.mediawiki.org/w/index.php?title=Extension:Graph/Demo/RawData:WorldMap-iso3-json&action=raw", "format": {"type": "topojson","feature": "countries"}, "transform": [ {         "type": "geopath", "value": "data", "scale": 80, "center": [-180,125], "translate": [0,0], "projection": "equirectangular" },       {          "type": "lookup", "keys": ["id"], "on": "highlights", "onKey": "id", "as": ["zipped"], "default": {"v": null, "country":"No data"} }     ]    }  ],  "scales": [ {     "name": "yearsScale", "type": "linear", "zero": false, "domain": [1960,2013], "range": "width" },   {      "name": "color", "type": "linear", "domain": {"data": "countries","field": "zipped.v"}, "domainMin": 1, "zero": false, "range": ["#FFEDBC", "#f83600"] } ],  "marks": [ {     "name": "yearLabel", "type": "text", "properties": { "enter": { "x": {"value": 0}, "y": {"value": 25}, "fontSize": {"value": 32}, "fontWeight": {"value": "bold"}, "fill": {"value": "steelblue"} },       "update": {"text": {"signal": "currentYear"}} }   },    {      "name": "scrollLine", "type": "rule", "properties": { "enter": { "x": {"value": 0}, "y": {"value": 40}, "x2": {"value": 500}, "stroke": {"value": "#000"}, "strokeWidth": {"value": 2} }     }    },    {      "name": "handle", "type": "path", "properties": { "enter": { "y": {"value": 40}, "path": {"value": "m-5.5,-10l0,20l11.5,-10l-11.5,-10z"}, "stroke": {"value": "#880"}, "strokeWidth": {"value": 2.5} },       "update": { "x": {"scale": "yearsScale","signal": "currentYear"}, "fill": {"value": "#fff"} },       "hover": {"fill": {"value": "#f00"}} }   },    {      "name": "map", "type": "path", "from": {"data": "countries"}, "properties": { "enter": {"path": {"field": "layout_path"}}, "update": { "fill":{ "rule": [ {               "predicate": { "name": "isNotNull", "id": {"field": "zipped.v"} },               "scale": "color", "field": "zipped.v"             }, {"value": "grey"} ]         }        },        "hover": {"fill": {"value": "#989898"}} }   },    {    "type": "text", "properties": { "enter": { "x": {"value": 500}, "y": {"value": 10}, "align": {"value": "right"}, "fontSize": {"value": 17}, "fill": {"value": "black"} },     "update": { "text": {"template": "\u007b{tooltipSignal.datum.zipped.country}} \u007b{tooltipSignal.datum.zipped.v}}"} }   }}  ],  "legends": [ {     "fill": "color", "title": "Fertility", "offset":-300, "properties": { "gradient": { "stroke": {"value": "transparent"} },       "title": { "fontSize": {"value": 14} }     }    }  ] }