UNPKG

hansight-datamap

Version:

Data of world map by hansight-llp

1,913 lines (1,798 loc) 637 kB
(function() { var svg; // Save off default references var d3 = window.d3, topojson = window.topojson; var defaultOptions = { scope: 'world', responsive: false, aspectRatio: 0.5625, setProjection: setProjection, projection: 'equirectangular', dataType: 'json', data: {}, done: function() {}, fills: { defaultFill: '#ABDDA4' }, filters: {}, geographyConfig: { dataUrl: null, hideAntarctica: true, hideHawaiiAndAlaska: false, borderWidth: 1, borderOpacity: 1, borderColor: '#FDFDFD', popupTemplate: function(geography, data) { return '<div class="hoverinfo"><strong>' + geography.properties.name + '</strong></div>'; }, popupOnHover: true, highlightOnHover: true, highlightFillColor: '#FC8D59', highlightBorderColor: 'rgba(250, 15, 160, 0.2)', highlightBorderWidth: 2, highlightBorderOpacity: 1 }, projectionConfig: { rotation: [97, 0] }, bubblesConfig: { borderWidth: 0, borderOpacity: 0, borderColor: '#FFFFFF', popupOnHover: true, radius: null, popupTemplate: function(geography, data) { return '<div class="hoverinfo"><strong>' + data.name + '</strong></div>'; }, fillOpacity: 0.75, animate: true, highlightOnHover: true, highlightFillColor: '#FC8D59', highlightBorderColor: 'rgba(250, 15, 160, 0.2)', highlightBorderWidth: 2, highlightBorderOpacity: 1, highlightFillOpacity: 0.85, exitDelay: 100, key: JSON.stringify }, arcConfig: { strokeColor: '#DD1C77', strokeWidth: 1, arcSharpness: 1, animationSpeed: 600, popupOnHover: false, popupTemplate: function(geography, data) { // Case with latitude and longitude if ((data.origin && data.destination) && data.origin.latitude && data.origin.longitude && data.destination.latitude && data.destination.longitude) { return '<div class="hoverinfo"><strong>Arc</strong><br>Origin: ' + JSON.stringify(data.origin) + '<br>Destination: ' + JSON.stringify(data.destination) + '</div>'; } // Case with only country name else if (data.origin && data.destination) { return '<div class="hoverinfo"><strong>Arc</strong><br>' + data.origin + ' -> ' + data.destination + '</div>'; } // Missing information else { return ''; } } } }; /* Getter for value. If not declared on datumValue, look up the chain into optionsValue */ function val(datumValue, optionsValue, context) { if (typeof context === 'undefined') { context = optionsValue; optionsValues = undefined; } var value = typeof datumValue !== 'undefined' ? datumValue : optionsValue; if (typeof value === 'undefined') { return null; } if (typeof value === 'function') { var fnContext = [context]; if (context.geography) { fnContext = [context.geography, context.data]; } return value.apply(null, fnContext); } else { return value; } } function addContainer(element, height, width) { this.svg = d3.select(element).append('svg') .attr('width', width || element.offsetWidth) .attr('data-width', width || element.offsetWidth) .attr('class', 'datamap') .attr('height', height || element.offsetHeight) .style('overflow', 'hidden'); // IE10+ doesn't respect height/width when map is zoomed in if (this.options.responsive) { d3.select(this.options.element).style({ 'position': 'relative', 'padding-bottom': (this.options.aspectRatio * 100) + '%' }); d3.select(this.options.element).select('svg').style({ 'position': 'absolute', 'width': '100%', 'height': '100%' }); d3.select(this.options.element).select('svg').select('g').selectAll('path').style('vector-effect', 'non-scaling-stroke'); } var defs = this.svg.append("svg:defs") // left -> right bright -> dark var gradient = defs.append("svg:linearGradient") .attr("id", "gradientLR") .attr("x1", "0%") .attr("y1", "0%") .attr("x2", "100%") .attr("y2", "0%") .attr("spreadMethod", "pad"); gradient.append("svg:stop") .attr("offset", "0%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 1); gradient.append("svg:stop") .attr("offset", "100%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 0); // right -> left bright -> dark gradient = defs.append("svg:linearGradient") .attr("id", "gradientRL") .attr("x1", "0%") .attr("y1", "0%") .attr("x2", "100%") .attr("y2", "0%") .attr("spreadMethod", "pad"); gradient.append("svg:stop") .attr("offset", "0%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 0); gradient.append("svg:stop") .attr("offset", "100%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 1); // top -> bottom bright -> dark gradient = defs.append("svg:linearGradient") .attr("id", "gradientTB") .attr("x1", "0%") .attr("y1", "0%") .attr("x2", "0%") .attr("y2", "100%") .attr("spreadMethod", "pad"); gradient.append("svg:stop") .attr("offset", "0%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 1); gradient.append("svg:stop") .attr("offset", "100%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 0); // bottom -> top bright -> dark gradient = defs.append("svg:linearGradient") .attr("id", "gradientBT") .attr("x1", "0%") .attr("y1", "0%") .attr("x2", "0%") .attr("y2", "100%") .attr("spreadMethod", "pad"); gradient.append("svg:stop") .attr("offset", "0%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 0); gradient.append("svg:stop") .attr("offset", "100%") .attr("stop-color", "#FE9900") .attr("stop-opacity", 1); return this.svg; } // setProjection takes the svg element and options function setProjection(element, options) { var width = options.width || element.offsetWidth; var height = options.height || element.offsetHeight; var projection, path; var svg = this.svg; if (options && typeof options.scope === 'undefined') { options.scope = 'world'; } if (options.scope === 'usa') { projection = d3.geo.albersUsa() .scale(width) .translate([width / 2, height / 2]); } else if (options.scope === 'world') { projection = d3.geo[options.projection]() .scale((width + 1) / 2 / Math.PI) .translate([width / 2, height / (options.projection === "mercator" ? 1.45 : 1.8)]); // .rotate([-115, 0]); } if (options.projection === 'orthographic') { svg.append("defs").append("path") .datum({ type: "Sphere" }) .attr("id", "sphere") .attr("d", path); svg.append("use") .attr("class", "stroke") .attr("xlink:href", "#sphere"); svg.append("use") .attr("class", "fill") .attr("xlink:href", "#sphere"); projection.scale(250).clipAngle(90).rotate(options.projectionConfig.rotation) } path = d3.geo.path() .projection(projection); return { path: path, projection: projection }; } function addStyleBlock() { if (d3.select('.datamaps-style-block').empty()) { d3.select('head').append('style').attr('class', 'datamaps-style-block') .html('.datamap path.datamaps-graticule { fill: none; stroke: #777; stroke-width: 0.5px; stroke-opacity: .5; pointer-events: none; } .datamap .labels {pointer-events: none;} .datamap path:not(.datamaps-arc), .datamap circle, .datamap line {stroke: #FFFFFF; vector-effect: non-scaling-stroke; stroke-width: 1px;} .datamaps-legend dt, .datamaps-legend dd { float: left; margin: 0 3px 0 0;} .datamaps-legend dd {width: 20px; margin-right: 6px; border-radius: 3px;} .datamaps-legend {padding-bottom: 20px; z-index: 1001; position: absolute; left: 4px; font-size: 12px; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;} .datamaps-hoverover {display: none; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .hoverinfo {padding: 4px; border-radius: 1px; background-color: #FFF; box-shadow: 1px 1px 5px #CCC; font-size: 12px; border: 1px solid #CCC; } .hoverinfo hr {border:1px dotted #CCC; }'); } } function drawSubunits(data) { var fillData = this.options.fills, colorCodeData = this.options.data || {}, geoConfig = this.options.geographyConfig; var subunits = this.svg.select('g.datamaps-subunits'); if (subunits.empty()) { subunits = this.addLayer('datamaps-subunits', null, true); } var geoData = topojson.feature(data, data.objects[this.options.scope]).features; if (geoConfig.hideAntarctica) { geoData = geoData.filter(function(feature) { return feature.id !== "ATA"; }); } if (geoConfig.hideHawaiiAndAlaska) { geoData = geoData.filter(function(feature) { return feature.id !== "HI" && feature.id !== 'AK'; }); } // $topojson --allow-empty -o final2.json -- chn.json world.json var chnData = topojson.feature(data, data.objects['chn']).features; geoData = chnData.concat(geoData); var geo = subunits.selectAll('path.datamaps-subunit').data(geoData); geo.enter() .append('path') .attr('d', this.path) .attr('class', function(d) { return 'datamaps-subunit ' + d.id; }) .attr('data-info', function(d) { return JSON.stringify(colorCodeData[d.id]); }) .style('fill', function(d) { if (d.id === 'CHN') return 'none'; // If fillKey - use that // Otherwise check 'fill' // Otherwise check 'defaultFill' var fillColor; var datum = colorCodeData[d.id]; if (datum && datum.fillKey) { fillColor = fillData[val(datum.fillKey, { data: colorCodeData[d.id], geography: d })]; } if (typeof fillColor === 'undefined') { fillColor = val(datum && datum.fillColor, fillData.defaultFill, { data: colorCodeData[d.id], geography: d }); } return fillColor; }) .style('stroke-width', geoConfig.borderWidth) .style('stroke-opacity', geoConfig.borderOpacity) .style('stroke-dasharray', function(d) { if (d.id.startsWith('CN.')) { return '1,2' } else return '0'; }) .style('stroke', geoConfig.borderColor); // var x = this.svg.select('g.datamaps-subunit CHN'); // x.style('stroke', 'white'); } function handleGeographyConfig() { var hoverover; var svg = this.svg; var self = this; var options = this.options.geographyConfig; if (options.highlightOnHover || options.popupOnHover) { svg.selectAll('.datamaps-subunit') .on('mouseover', function(d) { var $this = d3.select(this); var datum = self.options.data[d.id] || {}; if (options.highlightOnHover) { var previousAttributes = { 'fill': $this.style('fill'), 'stroke': $this.style('stroke'), 'stroke-width': $this.style('stroke-width'), 'fill-opacity': $this.style('fill-opacity') }; $this .style('fill', val(datum.highlightFillColor, options.highlightFillColor, datum)) .style('stroke', val(datum.highlightBorderColor, options.highlightBorderColor, datum)) .style('stroke-width', val(datum.highlightBorderWidth, options.highlightBorderWidth, datum)) .style('stroke-opacity', val(datum.highlightBorderOpacity, options.highlightBorderOpacity, datum)) .style('fill-opacity', val(datum.highlightFillOpacity, options.highlightFillOpacity, datum)) .attr('data-previousAttributes', JSON.stringify(previousAttributes)); // As per discussion on https://github.com/markmarkoh/datamaps/issues/19 if (!/((MSIE)|(Trident))/.test(navigator.userAgent)) { moveToFront.call(this); } } if (options.popupOnHover) { self.updatePopup($this, d, options, svg); } }) .on('mouseout', function() { var $this = d3.select(this); if (options.highlightOnHover) { // Reapply previous attributes var previousAttributes = JSON.parse($this.attr('data-previousAttributes')); for (var attr in previousAttributes) { $this.style(attr, previousAttributes[attr]); } } $this.on('mousemove', null); d3.selectAll('.datamaps-hoverover').style('display', 'none'); }); } function moveToFront() { this.parentNode.appendChild(this); } } // Plugin to add a simple map legend function addLegend(layer, data, options) { data = data || {}; if (!this.options.fills) { return; } var html = '<dl>'; var label = ''; if (data.legendTitle) { html = '<h2>' + data.legendTitle + '</h2>' + html; } for (var fillKey in this.options.fills) { if (fillKey === 'defaultFill') { if (!data.defaultFillName) { continue; } label = data.defaultFillName; } else { if (data.labels && data.labels[fillKey]) { label = data.labels[fillKey]; } else { label = fillKey + ': '; } } html += '<dt>' + label + '</dt>'; html += '<dd style="background-color:' + this.options.fills[fillKey] + '">&nbsp;</dd>'; } html += '</dl>'; var hoverover = d3.select(this.options.element).append('div') .attr('class', 'datamaps-legend') .html(html); } function addGraticule(layer, options) { var graticule = d3.geo.graticule(); this.svg.insert("path", '.datamaps-subunits') .datum(graticule) .attr("class", "datamaps-graticule") .attr("d", this.path); } function handleArcs(layer, data, options) { var self = this, selected = null, svg = this.svg; if (!data || (data && !data.slice)) { throw "Datamaps Error - arcs must be an array"; } // For some reason arc options were put in an `options` object instead of the parent arc // I don't like this, so to match bubbles and other plugins I'm moving it // This is to keep backwards compatability for (var i = 0; i < data.length; i++) { data[i] = defaults(data[i], data[i].options); delete data[i].options; } if (typeof options === "undefined") { options = defaultOptions.arcConfig; } var arcs = layer.selectAll('path.datamaps-arc').data(data, JSON.stringify); var path = d3.geo.path() .projection(self.projection); var longitudeCenter = self.projection.rotate()[0]; arcs .enter() .append('svg:path') .attr('class', 'datamaps-arc') .style('mix-blend-mode', 'screen') .style('stroke-linecap', 'round') // .style('stroke', function(datum) { // return val(datum.strokeColor, options.strokeColor, datum); // }) .style('fill', 'none') // .style('stroke', 'rgba(254,153,0,0.5)') .style('stroke', function(datum) { // Check if the current browser is Firefox? if (typeof InstallTrigger !== 'undefined') return 'rgba(254,153,0,0.5)'; // Otherwise return linearGradient; var originXY = self.latLngToXY(val(datum.origin.latitude, datum), val(datum.origin.longitude, datum)); var destXY = self.latLngToXY(val(datum.destination.latitude, datum), val(datum.destination.longitude, datum)); if (Math.abs(originXY[0] - destXY[0]) > Math.abs(originXY[1] - destXY[1])) { return (originXY[0] > destXY[0]) ? "url(#gradientLR)" : "url(#gradientRL)"; } else { return (originXY[1] > destXY[1]) ? "url(#gradientTB)" : "url(#gradientBT)"; } }) .style('stroke-width', function(datum) { return val(datum.strokeWidth, options.strokeWidth, datum); }) .attr('d', function(datum) { var originXY, destXY; if (typeof datum.origin === "string") { originXY = self.path.centroid(svg.select('path.' + datum.origin).data()[0]) } else { originXY = self.latLngToXY(val(datum.origin.latitude, datum), val(datum.origin.longitude, datum)) } if (typeof datum.destination === 'string') { destXY = self.path.centroid(svg.select('path.' + datum.destination).data()[0]) } else { destXY = self.latLngToXY(val(datum.destination.latitude, datum), val(datum.destination.longitude, datum)); } var midXY = [(originXY[0] + destXY[0]) / 2, (originXY[1] + destXY[1]) / 2]; if (options.greatArc) { // TODO: Move this to inside `if` clause when setting attr `d` var greatArc = d3.geo.greatArc() .source(function(d) { return [val(d.origin.longitude, d), val(d.origin.latitude, d)]; }) .target(function(d) { return [val(d.destination.longitude, d), val(d.destination.latitude, d)]; }); return path(greatArc(datum)) } var sharpness = val(datum.arcSharpness, options.arcSharpness, datum); return "M" + originXY[0] + ',' + originXY[1] + "S" + (midXY[0] + (50 * sharpness)) + "," + (midXY[1] - (75 * sharpness)) + "," + destXY[0] + "," + destXY[1]; }) .attr('data-info', function(datum) { return JSON.stringify(datum); }) .on('mouseover', function(datum) { var $this = d3.select(this); if (options.popupOnHover) { self.updatePopup($this, datum, options, svg); } }) .on('mouseout', function(datum) { var $this = d3.select(this); d3.selectAll('.datamaps-hoverover').style('display', 'none'); }) .transition() .delay(100) .style('fill', function(datum) { /* Thank you Jake Archibald, this is awesome. Source: http://jakearchibald.com/2013/animated-line-drawing-svg/ */ var length = this.getTotalLength(); this.style.transition = this.style.WebkitTransition = 'none'; // prevent dash when scaling // this.style.strokeDasharray = length + ' ' + length; // this.style.strokeDashoffset = length; this.getBoundingClientRect(); this.style.transition = this.style.WebkitTransition = 'stroke-dashoffset ' + val(datum.animationSpeed, options.animationSpeed, datum) + 'ms ease-out'; this.style.strokeDashoffset = '0'; return 'none'; }) arcs.exit() .transition() .style('opacity', 0) .remove(); } function handleLabels(layer, options) { var self = this; options = options || {}; var labelStartCoodinates = this.projection([-67.707617, 42.722131]); this.svg.selectAll(".datamaps-subunit") .attr("data-foo", function(d) { var center = self.path.centroid(d); var xOffset = 7.5, yOffset = 5; if (["FL", "KY", "MI"].indexOf(d.id) > -1) xOffset = -2.5; if (d.id === "NY") xOffset = -1; if (d.id === "MI") yOffset = 18; if (d.id === "LA") xOffset = 13; var x, y; x = center[0] - xOffset; y = center[1] + yOffset; var smallStateIndex = ["VT", "NH", "MA", "RI", "CT", "NJ", "DE", "MD", "DC"].indexOf(d.id); if (smallStateIndex > -1) { var yStart = labelStartCoodinates[1]; x = labelStartCoodinates[0]; y = yStart + (smallStateIndex * (2 + (options.fontSize || 12))); layer.append("line") .attr("x1", x - 3) .attr("y1", y - 5) .attr("x2", center[0]) .attr("y2", center[1]) .style("stroke", options.labelColor || "#000") .style("stroke-width", options.lineWidth || 1) } layer.append("text") .attr("x", x) .attr("y", y) .style("font-size", (options.fontSize || 10) + 'px') .style("font-family", options.fontFamily || "Verdana") .style("fill", options.labelColor || "#000") .text(function() { if (options.customLabelText && options.customLabelText[d.id]) { return options.customLabelText[d.id] } else { return d.id } }); return "bar"; }); } function handleBubbles(layer, data, options) { var self = this, fillData = this.options.fills, filterData = this.options.filters, svg = this.svg; if (!data || (data && !data.slice)) { throw "Datamaps Error - bubbles must be an array"; } var bubbles = layer.selectAll('circle.datamaps-bubble').data(data, options.key); bubbles .enter() .append('svg:circle') .attr('class', 'datamaps-bubble') .style('mix-blend-mode', 'screen') .attr('cx', function(datum) { var latLng; if (datumHasCoords(datum)) { latLng = self.latLngToXY(datum.latitude, datum.longitude); } else if (datum.centered) { if (datum.centered === 'USA') { latLng = self.projection([-98.58333, 39.83333]) } else { latLng = self.path.centroid(svg.select('path.' + datum.centered).data()[0]); } } if (latLng) return latLng[0]; }) .attr('cy', function(datum) { var latLng; if (datumHasCoords(datum)) { latLng = self.latLngToXY(datum.latitude, datum.longitude); } else if (datum.centered) { if (datum.centered === 'USA') { latLng = self.projection([-98.58333, 39.83333]) } else { latLng = self.path.centroid(svg.select('path.' + datum.centered).data()[0]); } } if (latLng) return latLng[1]; }) .attr('r', function(datum) { // If animation enabled start with radius 0, otherwise use full size. return options.animate ? 0 : val(datum.radius, options.radius, datum); }) .attr('data-info', function(datum) { return JSON.stringify(datum); }) .attr('filter', function(datum) { var filterKey = filterData[val(datum.filterKey, options.filterKey, datum)]; if (filterKey) { return filterKey; } }) .style('cursor', 'pointer') .style('stroke', function(datum) { return val(datum.borderColor, options.borderColor, datum); }) .style('stroke-width', function(datum) { return val(datum.borderWidth, options.borderWidth, datum); // return "RGBA(255, 205, 150, 1.00)"; }) .style('stroke-opacity', function(datum) { return 1; // return val(datum.borderOpacity, options.borderOpacity, datum); }) .style('fill-opacity', function(datum) { return val(datum.fillOpacity, options.fillOpacity, datum); // return 0.5; }) .style('fill', function(datum) { return "#FE9900"; // var fillColor = fillData[ val(datum.fillKey, options.fillKey, datum) ]; // return fillColor || fillData.defaultFill; }) .on('mouseover', function(datum) { var $this = d3.select(this); if (options.highlightOnHover) { // Save all previous attributes for mouseout var previousAttributes = { 'fill': $this.style('fill'), 'stroke': $this.style('stroke'), 'stroke-width': $this.style('stroke-width'), 'fill-opacity': $this.style('fill-opacity') }; $this .style('fill', val(datum.highlightFillColor, options.highlightFillColor, datum)) .style('stroke', val(datum.highlightBorderColor, options.highlightBorderColor, datum)) .style('stroke-width', val(datum.highlightBorderWidth, options.highlightBorderWidth, datum)) .style('stroke-opacity', val(datum.highlightBorderOpacity, options.highlightBorderOpacity, datum)) .style('fill-opacity', val(datum.highlightFillOpacity, options.highlightFillOpacity, datum)) .attr('data-previousAttributes', JSON.stringify(previousAttributes)); } if (options.popupOnHover) { self.updatePopup($this, datum, options, svg); } }) .on('mouseout', function(datum) { var $this = d3.select(this); if (options.highlightOnHover) { // Reapply previous attributes var previousAttributes = JSON.parse($this.attr('data-previousAttributes')); for (var attr in previousAttributes) { $this.style(attr, previousAttributes[attr]); } } d3.selectAll('.datamaps-hoverover').style('display', 'none'); }) bubbles.transition() .duration(400) .attr('r', function(datum) { return val(datum.radius, options.radius, datum); }) .transition() .duration(0) .attr('data-info', function(d) { return JSON.stringify(d); }); bubbles.exit() .transition() .delay(options.exitDelay) .attr("r", 0) .remove(); function datumHasCoords(datum) { return typeof datum !== 'undefined' && typeof datum.latitude !== 'undefined' && typeof datum.longitude !== 'undefined'; } } function defaults(obj) { Array.prototype.slice.call(arguments, 1).forEach(function(source) { if (source) { for (var prop in source) { // Deep copy if property not set if (obj[prop] == null) { if (typeof source[prop] == 'function') { obj[prop] = source[prop]; } else { obj[prop] = JSON.parse(JSON.stringify(source[prop])); } } } } }); return obj; } /************************************** Public Functions ***************************************/ function Datamap(options) { if (typeof d3 === 'undefined' || typeof topojson === 'undefined') { throw new Error('Include d3.js (v3.0.3 or greater) and topojson on this page before creating a new map'); } // Set options for global use this.options = defaults(options, defaultOptions); this.options.geographyConfig = defaults(options.geographyConfig, defaultOptions.geographyConfig); this.options.projectionConfig = defaults(options.projectionConfig, defaultOptions.projectionConfig); this.options.bubblesConfig = defaults(options.bubblesConfig, defaultOptions.bubblesConfig); this.options.arcConfig = defaults(options.arcConfig, defaultOptions.arcConfig); // Add the SVG container if (d3.select(this.options.element).select('svg').length > 0) { addContainer.call(this, this.options.element, this.options.height, this.options.width); } // Add core plugins to this instance this.addPlugin('bubbles', handleBubbles); this.addPlugin('legend', addLegend); this.addPlugin('arc', handleArcs); this.addPlugin('labels', handleLabels); this.addPlugin('graticule', addGraticule); // Append style block with basic hoverover styles if (!this.options.disableDefaultStyles) { addStyleBlock(); } return this.draw(); } // Resize map Datamap.prototype.resize = function() { var self = this; var options = self.options; if (options.responsive) { var newsize = options.element.clientWidth, oldsize = d3.select(options.element).select('svg').attr('data-width'); d3.select(options.element).select('svg').selectAll('g').attr('transform', 'scale(' + (newsize / oldsize) + ')'); } } // Actually draw the features(states & countries) Datamap.prototype.draw = function() { // Save off in a closure var self = this; var options = self.options; // Set projections and paths based on scope var pathAndProjection = options.setProjection.apply(this, [options.element, options]); this.path = pathAndProjection.path; this.projection = pathAndProjection.projection; // If custom URL for topojson data, retrieve it and render if (options.geographyConfig.dataUrl) { d3.json(options.geographyConfig.dataUrl, function(error, results) { if (error) throw new Error(error); self.customTopo = results; draw(results); }); } else { draw(this[options.scope + 'Topo'] || options.geographyConfig.dataJson); } return this; function draw(data) { // If fetching remote data, draw the map first then call `updateChoropleth` if (self.options.dataUrl) { // Allow for csv or json data types d3[self.options.dataType](self.options.dataUrl, function(data) { // In the case of csv, transform data to object if (self.options.dataType === 'csv' && (data && data.slice)) { var tmpData = {}; for (var i = 0; i < data.length; i++) { tmpData[data[i].id] = data[i]; } data = tmpData; } Datamaps.prototype.updateChoropleth.call(self, data); }); } drawSubunits.call(self, data); handleGeographyConfig.call(self); if (self.options.geographyConfig.popupOnHover || self.options.bubblesConfig.popupOnHover) { hoverover = d3.select(self.options.element).append('div') .attr('class', 'datamaps-hoverover') .style('z-index', 10001) .style('position', 'absolute'); } // Fire off finished callback self.options.done(self); } }; /************************************** TopoJSON ***************************************/ Datamap.prototype.worldTopo = { "type": "Topology", "objects": { "chn": { "type": "GeometryCollection", "geometries": [{ "type": "Polygon", "id": "CN.GS", "arcs": [ [0, 1, 2, 3, 4, 5, 6] ] }, { "type": "Polygon", "id": "CN.QH", "arcs": [ [7, 8, 9, -4] ] }, { "type": "MultiPolygon", "id": "CN.GX", "arcs": [ [ [10] ], [ [11] ], [ [12] ], [ [13, 14, 15, 16, 17] ] ] }, { "type": "Polygon", "id": "CN.GZ", "arcs": [ [18, -17, 19, 20, 21] ] }, { "type": "Polygon", "id": "CN.CQ", "arcs": [ [22, 23, -22, 24, 25] ] }, { "type": "Polygon", "id": "CN.BJ", "arcs": [ [26, 27, 28, 29] ] }, { "type": "MultiPolygon", "id": "CN.FJ", "arcs": [ [ [30] ], [ [31] ], [ [32] ], [ [33] ], [ [34] ], [ [35] ], [ [36] ], [ [37] ], [ [38] ], [ [39] ], [ [40] ], [ [41] ], [ [42] ], [ [43] ], [ [44] ], [ [45] ], [ [46] ], [ [47] ], [ [48, 49, 50, 51] ] ] }, { "type": "Polygon", "id": "CN.AH", "arcs": [ [52, 53, 54, 55, 56, 57] ] }, { "type": "MultiPolygon", "id": "CN.GD", "arcs": [ [ [58] ], [ [59] ], [ [60] ], [ [61] ], [ [62] ], [ [63] ], [ [64] ], [ [65] ], [ [66] ], [ [67] ], [ [68] ], [ [69] ], [ [70] ], [ [71] ], [ [72] ], [ [73] ], [ [74] ], [ [75] ], [ [76] ], [ [77] ], [ [78] ], [ [79] ], [ [80] ], [ [81, -50, 82, -14, 83] ] ] }, { "type": "Polygon", "id": "CN.XZ", "arcs": [ [-9, 84, 85, 86, 87] ] }, { "type": "Polygon", "id": "CN.XJ", "arcs": [ [-5, -10, -88, 88] ] }, { "type": "Polygon", "id": "CN.HA", "arcs": [ [89] ] }, { "type": "Polygon", "id": "CN.NX", "arcs": [ [90, -1, 91] ] }, { "type": "Polygon", "id": "CN.SA", "arcs": [ [92, 93, 94, -26, 95, -2, -91, 96] ] }, { "type": "Polygon", "id": "CN.SX", "arcs": [ [97, -93, 98, 99] ] }, { "type": "Polygon", "id": "CN.HU", "arcs": [ [-55, 100, 101, -23, -95, 102] ] }, { "type": "Polygon", "id": "CN.HN", "arcs": [ [103, -84, -18, -19, -24, -102] ] }, { "type": "Polygon", "id": "CN.SC", "arcs": [ [-96, -25, -21, 104, -85, -8, -3] ] }, { "type": "Polygon", "id": "CN.YN", "arcs": [ [-20, -16, 105, -86, -105] ] }, { "type": "MultiPolygon", "id": "CN.HB", "arcs": [ [ [106] ], [ [-28, 107] ], [ [108, 109, 110, -30, 111, 112, 113, 114, -100, 115] ] ] }, { "type": "Polygon", "id": "CN.HE", "arcs": [ [116, -56, -103, -94, -98, -115] ] }, { "type": "MultiPolygon", "id": "CN.LN", "arcs": [ [ [117] ], [ [118] ], [ [119] ], [ [120] ], [ [121] ], [ [122] ], [ [123] ], [ [124] ], [ [125] ], [ [126] ], [ [127] ], [ [128, -109, 129, 130, 131] ] ] }, { "type": "MultiPolygon", "id": "CN.SD", "arcs": [ [ [132] ], [ [133] ], [ [134] ], [ [135] ], [ [136] ], [ [137] ], [ [138, -57, -117, -114, 139] ], [ [140] ], [ [141] ] ] }, { "type": "MultiPolygon", "id": "CN.TJ", "arcs": [ [ [142] ], [ [143] ], [ [144] ], [ [145, -112, -29, -108, -27, -111] ] ] }, { "type": "Polygon", "id": "CN.JX", "arcs": [ [146, -51, -82, -104, -101, -54] ] }, { "type": "MultiPolygon", "id": "CN.JS", "arcs": [ [ [147] ], [ [148] ], [ [149] ], [ [150, 151, -58, -139, 152] ] ] }, { "type": "MultiPolygon", "id": "CN.SH", "arcs": [ [ [153] ], [ [154] ], [ [155, 156, -151] ], [ [157] ] ] }, { "type": "MultiPolygon", "id": "CN.ZJ", "arcs": [ [ [158] ], [ [159] ], [ [160] ], [ [161] ], [ [162] ], [ [163] ], [ [164] ], [ [165] ], [ [166] ], [ [167] ], [ [168] ], [ [169] ], [ [170] ], [ [171] ], [ [172] ], [ [173] ], [ [174] ], [ [175] ], [ [176] ], [ [177] ], [ [178] ], [ [179] ], [ [180] ], [ [181] ], [ [182] ], [ [183] ], [ [184] ], [ [185] ], [ [186] ], [ [187] ], [ [188] ], [ [189] ], [ [190] ], [ [191] ], [ [192] ], [ [193] ], [ [194] ], [ [-157, 195, -52, -147, -53, -152] ] ] }, { "type": "Polygon", "id": "CN.JL", "arcs": [ [196, 131, -132, -131, 197, 198] ] }, { "type": "Polygon", "id": "CN.NM", "arcs": [ [199, -198, -130, -116, -99, -97, -92, -7, 200] ] }, { "type": "Polygon", "id": "CN.HL", "arcs": [ [-199, -200, 201] ] }, { "type": "MultiPolygon", "id": "CN", "arcs": [ [ [202] ], [ [203] ], [ [204] ], [ [205] ], [ [206] ], [ [207] ], [ [208] ], [ [209] ] ] }] }, "world": { "type": "GeometryCollection", "geometries": [{ "type": "Polygon", "id": "AFG", "arcs": [ [210, 211, 212, 213, 214, 215] ] }, { "type": "MultiPolygon", "id": "AGO", "arcs": [ [ [216, 217, 218, 219] ], [ [220, 221, 222] ] ] }, { "type": "Polygon", "id": "ALB", "arcs": [ [223, 224, 225, 226, 227] ] }, { "type": "Polygon", "id": "ARE", "arcs": [ [228, 229, 230, 231, 232] ] }, { "type": "MultiPolygon", "id": "ARG", "arcs": [ [ [233, 234] ], [ [235, 236, 237, 238, 239, 240] ] ] }, { "type": "Polygon", "id": "ARM", "arcs": [ [241, 242, 243, 244, 245] ] }, { "type": "MultiPolygon", "id": "ATA", "arcs": [ [ [246] ], [ [247] ], [ [248] ], [ [249] ], [ [250] ], [ [251] ], [ [252] ], [ [253] ] ] }, { "type": "Polygon", "id": "ATF", "arcs": [ [254] ] }, { "type": "MultiPolygon", "id": "AUS", "arcs": [ [ [255] ], [ [256] ] ] }, { "type": "Polygon", "id": "AUT", "arcs": [ [257, 258, 259, 260, 261, 262, 263] ] }, { "type": "MultiPolygon", "id": "AZE", "arcs": [ [ [264, -245] ], [ [265, 266, -243, 267, 268] ] ] }, { "type": "Polygon", "id": "BDI", "arcs": [ [269, 270, 271] ] }, { "type": "Polygon", "id": "BEL", "arcs": [ [272, 273, 274, 275, 276] ] }, { "type": "Polygon", "id": "BEN", "arcs": [ [277, 278, 279, 280, 281] ] }, { "type": "Polygon", "id": "BFA", "arcs": [ [282, 283, 284, -280, 285, 286] ] }, { "type": "Polygon", "id": "BGD", "arcs": [ [287, 288, 289] ] }, { "type": "Polygon", "id": "BGR", "arcs": [ [290, 291, 292, 293, 294, 295] ] }, { "type": "MultiPolygon", "id": "BHS", "arcs": [ [ [296] ], [ [297] ], [ [298] ] ] }, { "type": "Polygon", "id": "BIH", "arcs": [ [299, 300, 301] ] }, { "type": "Polygon", "id": "BLR", "arcs": [ [302, 303, 304, 305, 306] ] }, { "type": "Polygon", "id": "BLZ", "arcs": [ [307, 308, 309] ] }, { "type": "Polygon", "id": "BOL", "arcs": [ [310, 311, 312, 313, -241] ] }, { "type": "Polygon", "id": "BRA", "arcs": [ [-237, 314, -313, 315, 316, 317, 318, 319, 320, 321, 322] ] }, { "type": "Polygon", "id": "BRN", "arcs": [ [323, 324] ] }, { "type": "Polygon", "id": "BTN", "arcs": [ [325, 326] ] }, { "type": "Polygon", "id": "BWA", "arcs": [ [327, 328, 329, 330] ] }, { "type": "Polygon", "id": "CAF", "arcs": [ [331, 332, 333, 334, 335, 336, 337] ] }, { "type": "MultiPolygon", "id": "CAN", "arcs": [ [ [338] ], [ [339] ], [ [340] ], [ [341] ], [ [342] ], [ [343] ], [ [344] ], [ [345] ], [ [346] ], [ [347] ], [ [348, 349, 350, 351] ], [ [352] ], [ [353] ], [ [354] ], [ [355] ], [ [356] ], [ [357] ], [ [358] ], [ [359] ], [ [360] ], [ [361] ], [ [362] ], [ [363] ], [ [364] ], [ [365] ], [ [366] ], [ [367] ], [ [368] ], [ [369] ], [ [370] ] ] }, { "type": "Polygon", "id": "CHE", "arcs": [ [-261, 371, 372, 373] ] }, { "type": "MultiPolygon", "id": "CHL", "arcs": [ [ [-234, 374] ], [ [-240, 375, 376, -311] ] ] }, { "type": "MultiPolygon", "id": "CHN", "arcs": [ [ [377] ], [ [378, 379, 380, 381, 382, 383, -327, 384, 385, 386, 387, -214, 388, 389, 390, 391, 392, 393] ] ] }, { "type": "Polygon", "id": "CIV", "arcs": [ [394, 395, 396, 397, -283, 398] ] }, { "type": "Polygon", "id": "CMR", "arcs": [ [399, 400, 401, 402, 403, 404, -338, 405] ] }, { "type": "Polygon", "id": "COD", "arcs": [ [406, 407, -270, 408, 409, -220, 410, -223, 411, -336, 412] ] }, { "type": "Polygon", "id": "COG", "arcs": [ [-222, 413, 414, -406, -337, -412] ] }, { "type": "Polygon", "id": "COL", "arcs": [ [415, 416, 417, 418, 419, -317, 420] ] }, { "type": "Polygon", "id": "CRI", "arcs": [ [421, 422, 423, 424] ] }, { "type": "Polygon", "id": "CUB", "arcs": [ [425] ] }, { "type": "Polygon", "id": "-99", "arcs": [ [426, 427] ] }, { "type": "Polygon", "id": "CYP", "arcs": [ [428, -428] ] }, { "type": "Polygon", "id": "CZE", "arcs": [ [-263, 429, 430, 431] ] }, { "type": "Polygon", "id": "DEU", "arcs": [ [432, 433, -430, -262, -374, 434, 435, -274, 436, 437, 438] ] }, { "type": "Polygon", "id": "DJI", "arcs": [ [439, 440, 441, 442] ] }, { "type": "MultiPolygon", "id": "DNK", "arcs": [ [ [443] ], [ [-439, 444] ] ] }, { "type": "Polygon", "id": "DOM", "arcs": [ [445, 446] ] }, { "type": "Polygon", "id": "DZA", "arcs": [ [447, 448, 449, 450, 451, 452, 453, 454] ] }, { "type": "Polygon", "id": "ECU", "arcs": [ [455, -416, 456] ] }, { "type": "Polygon", "id": "EGY", "arcs": [ [457, 458, 459, 460, 461] ] }