Daniel@0: "use strict"; Daniel@0: Daniel@0: App.module("GraphicsRenderingModule", function(GraphicsRenderingModule, App, Backbone, Marionette, $, _, Logger) { Daniel@0: Daniel@0: GraphicsRenderingModule.addInitializer(function(options){ Daniel@0: Daniel@0: // Map data source: http://data.okfn.org/data/datasets/geo-boundaries-world-110m#resource-countries Daniel@0: GraphicsRenderingModule.registerRenderer({ Daniel@0: id: "geography", Daniel@0: inherit: "_", Daniel@0: Daniel@0: defaultVegaConfig: { Daniel@0: comparisonMode: null, Daniel@0: Daniel@0: transformPropertiesByRegion: { Daniel@0: "planet": { Daniel@0: defaultScale: 500, Daniel@0: translateProportionX: 1/2, Daniel@0: translateProportionY: 1/2, Daniel@0: circleSizeMult: 20 Daniel@0: }, Daniel@0: "africa": { Daniel@0: defaultScale: 100, Daniel@0: translateProportionX: 0.20, Daniel@0: translateProportionY: .5, Daniel@0: circleSizeMult: 50 Daniel@0: }, Daniel@0: "europe": { Daniel@0: defaultScale: 70, Daniel@0: translateProportionX: 0.20, Daniel@0: translateProportionY: 1.90, Daniel@0: circleSizeMult: 50 Daniel@0: } Daniel@0: }, Daniel@0: Daniel@0: symbolSize: 20, Daniel@0: internalSpaceOffset: 6, Daniel@0: colorForData: "#3182bd", Daniel@0: Daniel@0: padding: {"top": 10, "left": 10, "bottom": 10, "right": 10}, Daniel@0: }, Daniel@0: Daniel@0: Daniel@0: _formVC: function(vc, data) { Daniel@0: vc.width = vc.totalWidth - vc.padding.left - vc.padding.right; Daniel@0: vc.height = vc.totalHeight - vc.padding.top - vc.padding.bottom; Daniel@0: Daniel@0: Daniel@0: // ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Daniel@0: // Data Daniel@0: Daniel@0: var countryStatsByCountryNumericCode = {}; Daniel@0: var hist = data.self.stats ? data.self.stats.hist : null; Daniel@0: if (!hist) { Daniel@0: hist = { Daniel@0: counts: [], Daniel@0: places: [] Daniel@0: } Daniel@0: } Daniel@0: Daniel@0: var countTotal = data.self.coverage.errors_count + data.self.coverage.failed_count; Daniel@0: var countFailures = countTotal; Daniel@0: Daniel@0: for (var i = hist.counts.length - 1; i >= 0; --i) { Daniel@0: var countryNumericCode = vc.placeCountryNumericCodes[hist.places[i]]; Daniel@0: countTotal += hist.counts[i]; Daniel@0: if (!countryNumericCode) { Daniel@0: countFailures += hist.counts[i]; Daniel@0: continue; Daniel@0: } Daniel@0: var country = vc.countriesByCountryNumericCode[countryNumericCode]; Daniel@0: Daniel@0: var countryStats = countryStatsByCountryNumericCode[countryNumericCode]; Daniel@0: if (!countryStats) { Daniel@0: countryStats = { Daniel@0: numericCode: country[1], Daniel@0: name: country[2], Daniel@0: count: 0 Daniel@0: }; Daniel@0: countryStatsByCountryNumericCode[countryNumericCode] = countryStats; Daniel@0: } Daniel@0: countryStats.count += hist.counts[i]; Daniel@0: } Daniel@0: Daniel@0: var countryStats = _.values(countryStatsByCountryNumericCode); Daniel@0: Daniel@0: for (var i = countryStats.length - 1; i >= 0; --i) { Daniel@0: var count = countryStats[i].count; Daniel@0: var percentage = 100 * count / countTotal; Daniel@0: countryStats[i].percentage = percentage; Daniel@0: } Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Data - points Daniel@0: vc.data.push({ Daniel@0: "name": "countries", Daniel@0: "values": vc.countries Daniel@0: }); Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Data - country outlines Daniel@0: vc.data.push({ Daniel@0: "name": "countryOutlines", Daniel@0: "values": vc.countryOutlines, Daniel@0: "format": { Daniel@0: "type": "topojson", Daniel@0: "feature": "countries" Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Data - country stats Daniel@0: vc.data.push({ Daniel@0: "name": "countryStats", Daniel@0: "values": countryStats Daniel@0: }); Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Data - country summary Daniel@0: var transformProperties = vc.transformPropertiesByRegion[vc.region]; Daniel@0: vc.data.push({ Daniel@0: "name": "countrySummary", Daniel@0: "source": "countryOutlines", Daniel@0: "transform": [ Daniel@0: { Daniel@0: "type": "geopath", Daniel@0: "value": "data", Daniel@0: "projection": "eckert3", Daniel@0: "scale": 100 / transformProperties.defaultScale * vc.width, Daniel@0: "translate": [ Daniel@0: vc.width * transformProperties.translateProportionX, Daniel@0: vc.height * transformProperties.translateProportionY Daniel@0: ] Daniel@0: }, Daniel@0: { "type": "lookup", "on": "countryStats", "onKey": "numericCode", Daniel@0: "keys": ["id"], "as": ["cs"], "default": {"count": 0, "percentage": 0}}, Daniel@0: Daniel@0: { "type": "lookup", "on": "countries", "onKey": "1", Daniel@0: "keys": ["id"], "as": ["tooltip"], "default": null} Daniel@0: ] Daniel@0: }); Daniel@0: Daniel@0: Daniel@0: // ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Daniel@0: // Scales Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Scale - color Daniel@0: vc.scales.push({ Daniel@0: "name": "color", Daniel@0: "type": "linear", Daniel@0: "domain": [0, 0.01, 50], Daniel@0: "clamp": true, Daniel@0: "range": ["#ccc", "#c6dbef", "#055893"] Daniel@0: }); Daniel@0: Daniel@0: Daniel@0: // ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Daniel@0: // Marks Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Mark - background (to catch mouse events and remove tooltips) Daniel@0: vc.marks.push({ Daniel@0: "type": "rect", Daniel@0: "properties": { Daniel@0: "enter": { Daniel@0: "x": {"value": -vc.padding.left}, Daniel@0: "y": {"value": -vc.padding.top}, Daniel@0: "fill": {"value": "#fff"}, Daniel@0: "y2": {"field": {"group": "height"}, "offset": vc.padding.left + vc.padding.right}, Daniel@0: "x2": {"field": {"group": "width"}, "offset": vc.padding.top + vc.padding.bottom}, Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Mark - countries as polygons Daniel@0: if (!vc.showCountriesAsCircles) { Daniel@0: vc.marks.push({ Daniel@0: "type": "path", Daniel@0: "from": { Daniel@0: "data": "countrySummary", Daniel@0: }, Daniel@0: "properties": { Daniel@0: "enter": { Daniel@0: "stroke": {"value": "#fff"}, Daniel@0: "path": {"field": "layout_path"} Daniel@0: }, Daniel@0: "update": { Daniel@0: "fill": {"scale": "color", "field": "cs.percentage"} Daniel@0: }, Daniel@0: "hover": { Daniel@0: "fill": {"value": "#000"}, Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: Daniel@0: // ............................................................. Daniel@0: // Mark - countries as circles Daniel@0: } else { Daniel@0: vc.marks.push({ Daniel@0: "type": "path", Daniel@0: "from": { Daniel@0: "data": "countrySummary", Daniel@0: }, Daniel@0: "properties": { Daniel@0: "enter": { Daniel@0: "stroke": {"value": "#fff"}, Daniel@0: "path": {"field": "layout_path"} Daniel@0: }, Daniel@0: "update": { Daniel@0: "fill": {"value": "#f0f0f0"} Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: vc.marks.push({ Daniel@0: "type": "symbol", Daniel@0: "from": { Daniel@0: "data": "countrySummary", Daniel@0: "transform": [{"type":"centroid", "field": "layout_path"}], Daniel@0: }, Daniel@0: "properties": { Daniel@0: "enter": { Daniel@0: //"size": {/*"scale": "color",*/ "value": 100}, Daniel@0: "size": {/*"scale": "color",*/ "field": "cs.percentage", "mult": transformProperties.circleSizeMult}, Daniel@0: "opacity": {"value": 0.5}, Daniel@0: "x": {"field": "centroid_x"}, Daniel@0: "y": {"field": "centroid_y"} Daniel@0: }, Daniel@0: "update": { Daniel@0: "fill": {"value": vc.colorForData} Daniel@0: }, Daniel@0: "hover": { Daniel@0: "fill": {"value": "#000"}, Daniel@0: } Daniel@0: } Daniel@0: }); Daniel@0: } Daniel@0: }, Daniel@0: }); Daniel@0: }); Daniel@0: }, Logger);