128 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div :id="id" class="world-map"></div>
 | |
| </template>
 | |
| <script>
 | |
| import 'd3';
 | |
| import * as d3 from 'd3';
 | |
| import 'topojson';
 | |
| import { throttle } from '@/util/throttle';
 | |
| 
 | |
| export default {
 | |
|   name: 'world-map',
 | |
|   props: {
 | |
|     mapData: {
 | |
|       type: Object,
 | |
|       default: () => ({})
 | |
|     },
 | |
|     points: {
 | |
|       type: Array,
 | |
|       default: () => []
 | |
|     }
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       id: this.randomString(),
 | |
|       color1: '#f6f9fc',
 | |
|       color2: '#adb5bd',
 | |
|       highlightFillColor: '#ced4da',
 | |
|       borderColor: 'white',
 | |
|       highlightBorderColor: 'white',
 | |
|       bubbleHighlightFillColor: '#11cdef',
 | |
|       bubbleFillColor: '#fb6340'
 | |
|     };
 | |
|   },
 | |
|   methods: {
 | |
|     generateColors(length) {
 | |
|       return d3
 | |
|         .scaleLinear()
 | |
|         .domain([0, length])
 | |
|         .range([this.color1, this.color2]);
 | |
|     },
 | |
|     generateMapColors() {
 | |
|       let mapDataValues = Object.values(this.mapData);
 | |
|       let maxVal = Math.max(...mapDataValues);
 | |
|       let colors = this.generateColors(maxVal);
 | |
|       let mapData = {};
 | |
|       let fills = {
 | |
|         defaultFill: '#EDF0F2'
 | |
|       };
 | |
|       for (let key in this.mapData) {
 | |
|         let val = this.mapData[key];
 | |
|         fills[key] = colors(val);
 | |
|         mapData[key] = {
 | |
|           fillKey: key,
 | |
|           value: val
 | |
|         };
 | |
|       }
 | |
|       return {
 | |
|         mapData,
 | |
|         fills
 | |
|       };
 | |
|     },
 | |
|     async initVectorMap() {
 | |
|       let DataMap = await import('datamaps');
 | |
|       DataMap = DataMap.default || DataMap
 | |
|       let { fills, mapData } = this.generateMapColors();
 | |
|       let worldMap = new DataMap({
 | |
|         scope: 'world',
 | |
|         element: document.getElementById(this.id),
 | |
|         fills,
 | |
|         data: mapData,
 | |
|         responsive: true,
 | |
|         geographyConfig: {
 | |
|           borderColor: this.borderColor,
 | |
|           borderWidth: 1,
 | |
|           borderOpacity: 1,
 | |
|           highlightFillColor: this.highlightFillColor,
 | |
|           highlightBorderColor: this.highlightBorderColor,
 | |
|           highlightBorderWidth: 1,
 | |
|           highlightBorderOpacity: 1
 | |
|         }
 | |
|       });
 | |
|       let bubbleOptions = {
 | |
|         radius: 2,
 | |
|         borderWidth: 4,
 | |
|         highlightBorderWidth: 4,
 | |
|         fillKey: this.bubbleFillColor,
 | |
|         fillColor: this.bubbleFillColor,
 | |
|         borderColor: this.bubbleFillColor,
 | |
|         highlightFillColor: this.bubbleHighlightFillColor,
 | |
|         highlightBorderColor: this.bubbleHighlightFillColor
 | |
|       }
 | |
|       let bubblePoints = this.points.map(point => {
 | |
|         return {
 | |
|           ...bubbleOptions,
 | |
|           ...point
 | |
|         }
 | |
|       })
 | |
|       worldMap.bubbles(bubblePoints, {
 | |
|         popupTemplate: function(geo, data) {
 | |
|           return '<div class="hoverinfo">' + data.name
 | |
|         }
 | |
|       });
 | |
|       let resizeFunc = worldMap.resize.bind(worldMap);
 | |
|       window.addEventListener(
 | |
|         'resize',
 | |
|         () => {
 | |
|           throttle(resizeFunc, 40);
 | |
|         },
 | |
|         false
 | |
|       );
 | |
|     },
 | |
|     randomString() {
 | |
|       let text = "";
 | |
|       let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 | |
| 
 | |
|       for (let i = 0; i < 5; i++)
 | |
|         text += possible.charAt(Math.floor(Math.random() * possible.length));
 | |
| 
 | |
|       return text;
 | |
|     }
 | |
|   },
 | |
|   async mounted() {
 | |
|     this.initVectorMap();
 | |
|   }
 | |
| };
 | |
| </script>
 | |
| <style></style>
 |