It is a Vue port of the javascript-based DataMaps
# project clone $ git clone https://github.com/Seungwoo321/vue-datamaps.git # install dependencies $ npm install # run $ npm run dev
# install
$ npm install vue-datamaps
- json data is no longer required.
main.js
import Vue from 'vue' import VueDatamaps from 'vue-datamaps' Vue.use(VueDatamaps)
vue template
<template> <div id="app"> <vue-datamaps></vue-datamaps> </div> </template>
vue template
<template> <div id="app"> <vue-datamaps></vue-datamaps> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps } } </script>
<template> <div> <h4>Basic:</h4> <vue-datamaps/> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps } } </script> <style> </style>
vue-datamaps-demo-state-label.png
<template> <div> <h4>State Labels:</h4> <vue-datamaps labels :scope="scope" :geographyConfig="geographyConfig" :fills="fills" :data="data" popupTemplate @custom:popup="popupTemplate" > <div slot="hoverinfo" class="hoverinfo" style="white-space: pre-line;"> {{ popupData }} </div> </vue-datamaps> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps }, data () { return { scope: 'usa', geographyConfig: { highlightBorderColor: '#bada55', highlightBorderWidth: 3 }, fills: { 'Republican': '#CC4731', 'Democrat': '#306596', 'Heavy Democrat': '#667FAF', 'Light Democrat': '#A9C0DE', 'Heavy Republican': '#CA5E5B', 'Light Republican': '#EAA9A8', defaultFill: '#EDDC4E' }, data: { 'AZ': { 'fillKey': 'Republican', 'electoralVotes': 5 }, 'CO': { 'fillKey': 'Light Democrat', 'electoralVotes': 5 }, 'DE': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'FL': { 'fillKey': 'UNDECIDED', 'electoralVotes': 29 }, 'GA': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'HI': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'ID': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'IL': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'IN': { 'fillKey': 'Republican', 'electoralVotes': 11 }, 'IA': { 'fillKey': 'Light Democrat', 'electoralVotes': 11 }, 'KS': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'KY': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'LA': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'MD': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'ME': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'MA': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'MN': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'MI': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'MS': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'MO': { 'fillKey': 'Republican', 'electoralVotes': 13 }, 'MT': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'NC': { 'fillKey': 'Light Republican', 'electoralVotes': 32 }, 'NE': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'NV': { 'fillKey': 'Heavy Democrat', 'electoralVotes': 32 }, 'NH': { 'fillKey': 'Light Democrat', 'electoralVotes': 32 }, 'NJ': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'NY': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'ND': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'NM': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'OH': { 'fillKey': 'UNDECIDED', 'electoralVotes': 32 }, 'OK': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'OR': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'PA': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'RI': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'SC': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'SD': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'TN': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'TX': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'UT': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'WI': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'VA': { 'fillKey': 'Light Democrat', 'electoralVotes': 32 }, 'VT': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'WA': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'WV': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'WY': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'CA': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'CT': { 'fillKey': 'Democrat', 'electoralVotes': 32 }, 'AK': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'AR': { 'fillKey': 'Republican', 'electoralVotes': 32 }, 'AL': { 'fillKey': 'Republican', 'electoralVotes': 32 } }, popupData: '' } }, methods: { popupTemplate ({ geography, datum }) { this.popupData = `${geography.properties.name}\nElectoral Votes: ${datum.electoralVotes}` } } } </script> <style> </style>
<template> <div> <h4>Bubbles:</h4> <vue-datamaps :geographyConfig="geographyConfig" :bubblesConfig="bubblesConfig" :fills="fills" @custom:popup-bubble="popupTemplate" bubbles > <div slot="hoverBubbleInfo" class="hoverinfo" style="text-align:center;"> <b>Yield</b>: {{ popupData.yeild }}<br> Exploded on {{ popupData.date }} by the {{ popupData.country }} </div> </vue-datamaps> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps }, data () { return { geographyConfig: { popupOnHover: true, highlightOnHover: true }, fills: { defaultFill: '#ABDDA4', USA: 'blue', RUS: 'red' }, bubblesConfig: { popupTemplate: true, data: [ { name: 'Not a bomb, but centered on Brazil', radius: 23, centered: 'BRA', country: 'USA', yeild: 0, fillKey: 'USA', date: '1954年03月01日' }, { name: 'Not a bomb', radius: 15, yeild: 0, country: 'USA', centered: 'USA', date: '1986年06月05日', significance: 'Centered on US', fillKey: 'USA' }, { name: 'Castle Bravo', radius: 25, yeild: 15000, country: 'USA', significance: 'First dry fusion fuel "staged" thermonuclear weapon; a serious nuclear fallout accident occurred', fillKey: 'USA', date: '1954年03月01日', latitude: 11.415, longitude: 165.1619 }, { name: 'Tsar Bomba', radius: 70, yeild: 50000, country: 'USSR', fillKey: 'RUS', significance: 'Largest thermonuclear weapon ever tested—scaled down from its initial 100 Mt design by 50%', date: '1961年10月31日', latitude: 73.482, longitude: 54.5854 } ] }, popupData: { yeild: '', date: '', country: '' } } }, methods: { popupTemplate ({ datum }) { this.popupData = { yeild: datum.yeild, date: datum.date, country: datum.country } } } } </script> <style> </style>
<template> <div> <h4>Arcs:</h4> <vue-datamaps :scope="scope" :fills="fills" :data="data" :geographyConfig="geographyConfig" :arcConfig="arcConfig" arc /> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps }, data () { return { geographyConfig: { popupOnHover: true, highlightOnHover: true }, scope: 'usa', fills: { defaultFill: '#ABDDA4', win: '#0fa0fa' }, data: { 'TX': { fillKey: 'win' }, 'FL': { fillKey: 'win' }, 'NC': { fillKey: 'win' }, 'CA': { fillKey: 'win' }, 'NY': { fillKey: 'win' }, 'CO': { fillKey: 'win' } }, arcConfig: { popupOnHover: true, data: [ { origin: 'CA', destination: 'TX' }, { origin: 'OR', destination: 'TX' }, { origin: 'NY', destination: 'TX' }, { origin: { latitude: 40.639722, longitude: -73.778889 }, destination: { latitude: 37.618889, longitude: -122.375 } }, { origin: { latitude: 30.194444, longitude: -97.67 }, destination: { latitude: 25.793333, longitude: -80.290556 }, options: { strokeWidth: 2, strokeColor: 'rgba(100, 10, 200, 0.4)', greatArc: true } }, { origin: { latitude: 39.861667, longitude: -104.673056 }, destination: { latitude: 35.877778, longitude: -78.7875 } } ], strokeWidth: 1, arcSharpness: 1.4 } } } } </script> <style> </style>
vue-datamaps-demo-graticules.png
<template> <div> <h4>Projections & Graticules:</h4> <vue-datamaps :scope="scope" :projection="projection" :projectionConfig="projectionConfig" :fills="fills" :data="data" :arcConfig="arcConfig" arc /> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' import * as d3 from 'd3v4' export default { components: { VueDatamaps }, data () { return { scope: 'world', projection: 'Orthographic', fills: { defaultFill: '#ABDDA4', gt50: d3.schemeCategory20[Math.floor(Math.random() * 20)], eq50: d3.schemeCategory20b[Math.floor(Math.random() * 20)], lt25: d3.schemeCategory20c[Math.floor(Math.random() * 20)], gt75: d3.schemeCategory20[Math.floor(Math.random() * 20)], lt50: d3.schemeCategory10[Math.floor(Math.random() * 10)], eq0: d3.schemeCategory10[Math.floor(Math.random() * 1)], pink: '#0fa0fa', gt500: d3.schemeCategory10[Math.floor(Math.random() * 1)] }, data: { 'USA': { fillKey: 'lt50' }, 'MEX': { fillKey: 'lt25' }, 'CAN': { fillKey: 'gt50' }, 'GTM': { fillKey: 'gt500' }, 'HND': { fillKey: 'eq50' }, 'BLZ': { fillKey: 'pink' }, 'GRL': { fillKey: 'eq0' } }, projectionConfig: { rotation: [97, -30] }, arcConfig: { popupOnHover: false, data: [ { origin: { latitude: 61, longitude: -149 }, destination: { latitude: -22, longitude: -43 } } ], greatArc: true, animationSpeed: 2000 } } } } </script> <style> </style>
<template> <div> <h4>Zoom:</h4> <vue-datamaps :scope="scope" :data="data" :fills="fills" :bubblesConfig="bubblesConfig" bubbles @custom:popup-bubble="popupTemplate" :setProjection="setProjection('zoom')" > <div slot="hoverBubbleInfo" class="hoverinfo" style="text-align:center;"> {{ popupData.name }} </div> </vue-datamaps> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' import * as d3 from 'd3v4' export default { components: { VueDatamaps }, data () { return { scope: 'world', fills: { defaultFill: '#ABDDA4', gt50: d3.schemeCategory20[Math.floor(Math.random() * 20)], eq50: d3.schemeCategory20b[Math.floor(Math.random() * 20)], lt25: d3.schemeCategory20c[Math.floor(Math.random() * 20)], gt75: d3.schemeCategory20[Math.floor(Math.random() * 20)], lt50: d3.schemeCategory10[Math.floor(Math.random() * 10)], eq0: d3.schemeCategory10[Math.floor(Math.random() * 1)], pink: '#0fa0fa', gt500: d3.schemeCategory10[Math.floor(Math.random() * 1)] }, data: { 'ZAF': { fillKey: 'gt50' }, 'ZWE': { fillKey: 'lt25' }, 'NGA': { fillKey: 'lt50' }, 'MOZ': { fillKey: 'eq50' }, 'MDG': { fillKey: 'eq50' }, 'EGY': { fillKey: 'gt75' }, 'TZA': { fillKey: 'gt75' }, 'LBY': { fillKey: 'eq0' }, 'DZA': { fillKey: 'gt500' }, 'SSD': { fillKey: 'pink' }, 'SOM': { fillKey: 'gt50' }, 'GIB': { fillKey: 'eq50' }, 'AGO': { fillKey: 'lt50' } }, bubblesConfig: { popupOnHover: true, popupTemplate: true, data: [ { name: 'Bubble 1', latitude: 21.32, longitude: -7.32, radius: 45, fillKey: 'gt500' }, { name: 'Bubble 2', latitude: 12.32, longitude: 27.32, radius: 25, fillKey: 'eq0' }, { name: 'Bubble 3', latitude: 0.32, longitude: 23.32, radius: 35, fillKey: 'lt25' }, { name: 'Bubble 4', latitude: -31.32, longitude: 23.32, radius: 55, fillKey: 'eq50' } ] }, popupData: { name: '' } } }, methods: { popupTemplate ({ datum }) { this.popupData.name = `Bubble for ${datum.name}` }, setProjection (type) { const createProjection = { korea: function (d3, element) { const projection = d3.geoMercator().center([0, 0]) .rotate([-128, -36]) .scale(element.offsetWidth * 6) .translate([element.offsetWidth / 2, element.offsetHeight / 2]) const path = d3.geoPath().projection(projection) return { projection, path } }, zoom: function (d3, element) { var projection = d3.geoEquirectangular() .center([23, -3]) .rotate([4.4, 0]) .scale(element.offsetHeight * 0.6) .translate([element.offsetWidth / 2, element.offsetHeight / 2]) var path = d3.geoPath() .projection(projection) return { path: path, projection: projection } } } return createProjection[type] } } } </script> <style> </style>
vue-datamaps-demo-south-korea.png
<template> <div> <h4>South Korea:</h4> <vue-datamaps :scope="scope" :setProjection="setProjection('korea')" :fills="fills" :data="data" /> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps }, data () { return { scope: 'kor', fills: { color1: '#fa0fa0', color2: '#A9C0DE' }, data: { 'KR.SO': { fillKey: 'color1' }, 'KR.TG': { fillKey: 'color2' } } } }, methods: { setProjection (type) { const createProjection = { korea: function (d3, element) { const projection = d3.geoMercator().center([0, 0]) .rotate([-128, -36]) .scale(element.offsetWidth * 6) .translate([element.offsetWidth / 2, element.offsetHeight / 2]) const path = d3.geoPath().projection(projection) return { projection, path } }, zoom: function (d3, element) { var projection = d3.geoEquirectangular() .center([23, -3]) .rotate([4.4, 0]) .scale(element.offsetHeight * 0.6) .translate([element.offsetWidth / 2, element.offsetHeight / 2]) var path = d3.geoPath() .projection(projection) return { path: path, projection: projection } } } return createProjection[type] } } } </script> <style> </style>
vue-datamaps-demo-custom-color.png
<template> <div> <h4>Custom Color:</h4> <vue-datamaps :fills="fills" :data="data" :geographyConfig="geographyConfig" bubbles :bubblesConfig="bubblesConfig" /> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps }, data () { return { bubblesConfig: { data: [ { name: 'Area 1', radius: 23, centered: 'BRA' }, { name: 'Area 2', radius: 15, centered: 'USA' }, { name: 'Area 3', radius: 50, latitude: 73.482, longitude: 54.5854 } ], highlightBorderColor: '#FFFFFF', highlightFillColor: '#F8A900' }, geographyConfig: { popupOnHover: false, highlightOnHover: false, borderWidth: 0 }, data: { USA: { fillKey: 'active' }, RUS: { fillKey: 'active' }, DEU: { fillKey: 'active' }, BRA: { fillKey: 'active' } }, fills: { defaultFill: '#3B3D46', active: '#F8A900' } } } } </script> <style> </style>
vue-datamaps-demo-aws-region.png
<template> <div> <h4>AWS Region:</h4> <vue-datamaps :geographyConfig="geographyConfig" :fills="fills" :arcConfig="arcConfig" arc aws-regions :awsRegionsConfig="awsRegionsConfig" @custom:popup-arc="popupTemplate" > <div slot="hoverArcInfo" class="hoverinfo"> <strong>{{ popupData.title }}</strong><br> {{ popupData.origin }} ▶▶▶ {{ popupData.destination }} </div> </vue-datamaps> </div> </template> <script> import { VueDatamaps } from 'vue-datamaps' export default { components: { VueDatamaps }, data () { return { geographyConfig: { dataUrl: '', popupOnHover: false, highlightOnHover: false }, fills: { defaultFill: '#cfcfcf', active: '#0b5fd6' }, awsRegionsConfig: { popupOnHover: true, data: [ { code: 'ap-northeast-2', fillKey: 'active' }, { code: 'ap-northeast-1', fillKey: 'active' }, { code: 'us-east-2', fillKey: 'active' }, { code: 'eu-north-1', fillKey: 'active' }, { code: 'ca-central-1', fillKey: 'active' } ] }, arcConfig: { popupOnHover: true, popupTemplate: true, data: [ { origin: 'ap-northeast-2', destination: 'ap-northeast-1', options: { arcSharpness: 0.5 } }, { origin: 'ap-northeast-1', destination: 'ap-northeast-2', options: { arcSharpness: 0.5 } }, { origin: 'us-east-2', destination: 'ap-northeast-2', options: { arcSharpness: 3 } }, { origin: 'ap-northeast-2', destination: 'us-east-2', options: { arcSharpness: 3 } }, { origin: 'eu-north-1', destination: 'ap-northeast-2', options: { strokeColor: 'red', arcSharpness: 2 } }, { origin: 'ca-central-1', destination: 'eu-west-2', options: { strokeColor: 'rgba(100, 10, 200, 0.4)', arcSharpness: 3 } } ], strokeColor: '#0b5fd6', greatArc: true, animationSpeed: 2000 }, popupData: { title: 'DataTransfer', origin: '', destination: '' } } }, methods: { popupTemplate (datum) { this.popupData.origin = datum.origin.full_name this.popupData.destination = datum.destination.full_name } } } </script> <style> </style>
- type: String
- value: world, usa, custom_map
Same as the original.
- type: Function
- value: See sample code.
Same as original but d3 version different.
- type: String
- value: Equirectangular, Orthographic, Mercator
Same as original but PascalCase.
- type: String
- value json, csv
Same as original.
- type: Object
- value: See sample code.
Same as original.
- type: Function
Not implemented.
- type: Object
- value: The keys in this object map to the "fillKey" of [data] or [data of bubbles]
Same as original.
- type: Object
- value: See sample code.
Same as original but not include popupTemplate
.
- type: Object
- value: See sample code.
Same as original but not include popupTemplate
.
- type: Boolean
- value: true, false
If
bubblesConfig
required.
- type: Object
- value: See sample code.
Same as original but not include popupTemplate
.
- type: Boolean
- value: true, false
If arcConfig
required.
- type: Boolean
- value: true, false
Not implemented.
- type: Object
- value: See sample code.
Same as original.
- type: Boolean
- value: true, false
If labelsConfig
required.
- type: Boolean
- value: true, false
If slot hoverinfo
and event custom:popup
||custom:popup-bubble
||custom:popup-arc
||custom:popup-region
|| required.
{ scope: 'world', setProjection: (d3, element) => { let projection = null let path = null if (this.scope === 'usa') { projection = d3.geoAlbersUsa() .scale(this.svgWidth) .translate([this.svgWidth / 2, this.svgHeight / 2]) } else if (this.scope === 'world') { projection = d3[`geo${this.projection}`]() .scale((this.svgWidth + 1) / 2 / Math.PI) .translate([this.svgWidth / 2, this.svgHeight / (this.projection === 'Mercator' ? 1.45 : 1.8)]) } if (this.projection === 'Orthographic') { this.svg.append('defs').append('path') .datum({ type: 'Sphere' }) .attr('id', 'sphere') .attr('d', path) this.svg.append('use') .attr('class', 'stroke') .attr('xlink:href', '#sphere') this.svg.append('use') .attr('class', 'fill') .attr('xlink:href', '#sphere') projection.scale(this.svgWidth / Math.PI * 0.9).clipAngle(90).rotate(this.projectionConfigOptions.rotation) } path = d3.geoPath() .projection(projection) return { projection, path } }, projection: 'Equirectangular', dataType: 'json', data: {}, done: function () { return {} }, fills: { authorHasTraveledTo: '#fa0fa0', defaultFill: '#ABDDA4' }, geographyConfig: { dataUrl: null, hideAntarctica: true, hideHawaiiAndAlaska: false, borderWidth: 1, borderOpacity: 1, borderColor: '#FDFDFD', popupOnHover: true, highlightOnHover: true, highlightFillColor: '#FC8D59', highlightBorderColor: 'rgba(250, 15, 160, 0.2)', highlightBorderWidth: 2, highlightBorderOpacity: 1, highlightFillOpacity: 0.85 }, projectionConfig: { rotation: [97, 0] }, bubblesConfig: { borderWidth: 2, borderOpacity: 1, borderColor: '#FFFFFF', popupOnHover: true, radius: null, 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, data: [] }, bubbles: false, arcConfig: { strokeColor: '#DD1C77', strokeWidth: 1, arcSharpness: 1, animationSpeed: 600, popupOnHover: false, data: [] }, arc: false, disableDefaultStyles: false, labelsConfig: { fontSize: 10, fontFamily: 'Verdana', labelColor: '#000', lineWidth: 1 }, labels: false, popupTemplate: false, awsRegions: false, awsRegionsConfig: { strokeColor: '#0b5fd6', strokeWidth: 1.5, defaultFill: 'transparent', highlightFillOpacity: 1, showPrivateRegions: false, popupOnHover: false, data: [] } }
- when geography mouse hover:
- slot:
hoverinfo
- event:
custom:popup
- slot:
<div slot="hoverinfo" class="hoverinfo" style="text-align:center;"> <!-- ... --> </div>
- when bubbles mouse hover:
- slot:
hoverBubbleInfo
- event:
custom:popup-bubble
- slot:
<div slot="hoverBubbleInfo" class="hoverinfo" style="text-align:center;"> <!-- ... --> </div>
- when arc mouse hover:
- slot:
hoverArcInfo
- event:
custom:popup-arc
- slot:
<div slot="hoverArcInfo" class="hoverinfo" style="text-align:center;"> <!-- ... --> </div>
-
when aws-region mouse hover
- slot:
hoverRegionInfo
- event:
custom:popup-region
- slot:
<div slot="hoverRegionInfo" class="hoverinfo" style="text-align:center;"> <!-- ... --> </div>
- markmarkoh/datamaps - original
- btmills/react-datamaps - React-based datamaps library
- jsonmaur/aws-regions - AWS Regions and Availability Zones
MIT