实现其实也简单,创建一个组件
<template> <div id="centerBottomMap"> <div class="bg-color-black"> <div class="d-flex pt-2 pl-2"> <span> <icon name="map" class="text-icon"></icon> </span> <span class="fs-xl text mx-2">用户所在城市分布</span> </div> <div class="d-flex ai-center flex-column body-box"> <centerMap :cdata="cdata"/> </div> </div> </div> </template> <script> import centerMap from '@/components/echart/centerMap' import {getUserCityData} from "@/api/statistics"; export default { data() { return { timing: null, cdata: {} } }, components: { centerMap }, mounted() { this.getData() }, beforeDestroy () { }, methods:{ getData() { //从后台获取用户城市分布数据 getUserCityData().then(res => { if (res.code === 0) { this.cdata = { regionCode: 'china', data: res.data } console.info(this.cdata) } }); } } } </script> <style lang="scss" scoped> #centerBottomMap { $box-height: 440px; $box-width: 100%; height: $box-height; width: $box-width; border-radius: 5px; padding: 0 16px; min-width: $box-width; .bg-color-black { padding: 5px; height: $box-height; width: $box-width; border-radius: 10px; } .text { color: #c3cbde; } .body-box { border-radius: 10px; overflow: hidden; .dv-cap-chart { width: 100%; height: 160px; } } } </style>
后台数据类似这样
以列表形式返回
然后我们再来看centerMap/index.vue
<template> <Echart :options="options" ref="map" height="410px" width="680px"/> </template> <script> import map from '@/common/map' export default { data() { return { length: 34, options: {}, }; }, props: { cdata: { type: Object, default: () => ({}) }, }, watch: { cdata: { handler (newData) { if (newData !== undefined && newData.data !== undefined) { let name = newData.regionCode let _data = newData.data let mapData = map.mapJson this.$echarts.registerMap(name, mapData); let cityCenter = {} let arr = mapData.features; //根据geo json获取省份中心点 arr.map((item) => { cityCenter[item.properties.name] = item.properties.centroid || item.properties.center; }); let data = []; _data.map((item) => { let name = item.name let value = item.value || 0 if (cityCenter[name]) { data.push({ name: name, value: cityCenter[name].concat(value), }); } }); console.info(data) this.length = data.length this.init(name, data); } }, immediate: true, deep: true } }, methods: { init(name, data) { let top = 30; let zoom = 1.15 let scale = 0.95 this.options = { backgroundColor: "rgba(0,0,0,0)", tooltip: { show: true, trigger: 'item', textStyle: { fontSize: 16, lineHeight: 22, }, formatter: function (params) { if (params.data) { return params.name + ":" + params.data["value"][2]; } else { return params.name; } }, backgroundColor: "rgba(0,0,0,.6)", borderColor: "rgba(147, 235, 248, .8)", textStyle: { color: "#FFF", }, position: point => { // 固定在顶部 return [point[0] + 5, point[1] - 20]; }, }, legend: { show: false, }, visualMap: { show: false, left: 0, bottom: 20, pieces: [ { gte: 1000, label: "1000个以上" }, // 不指定 max,表示 max 为无限大(Infinity)。 { gte: 600, lte: 999, label: "600-999个" }, { gte: 200, lte: 599, label: "200-599个" }, { gte: 50, lte: 199, label: "49-199个" }, { gte: 10, lte: 49, label: "10-49个" }, { lte: 9, label: "1-9个" }, // 不指定 min,表示 min 为无限大(-Infinity)。 ], inRange: { color: "#0782b7", }, /*inRange: { // 渐变颜色,从小到大 color: [ "#c3d7df", "#5cb3cc", "#8abcd1", "#66a9c9", "#2f90b9", "#1781b5", ], },*/ textStyle: { color: "#fff", }, }, geo: { map: name, roam: false, selectedMode: false, //是否允许选中多个区域 zoom: zoom, top: top, aspectScale: scale, //长宽比 show: true, }, series: [ { type: "map", map: name, aspectScale: scale, //长宽比 zoom: zoom, top: top, data: data, //数据 selectedMode: false, //是否允许选中多个区域 geoIndex: 1, //地图省份选中样式 emphasis: { label: { show: true, }, itemStyle: { areaColor: "#389BB7", // 背景色,默认是黄色 borderWidth: 1, }, }, //地图背景色 itemStyle: { color: "#47C1BF", areaColor: 'rgba(19,54,162, .5)', borderColor: 'rgba(0,242,252,.3)', borderWidth: 1, shadowBlur: 7, shadowColor: '#47C1BF', }, }, { data: data || [], type: "effectScatter", coordinateSystem: "geo", symbolSize: function (val) { val = val[2] || 0 if (val >= 5000) return 10; else if (val >= 1000) return 5; else if (val >= 800) return 4; else if (val >= 600) return 3; else if (val >= 400) return 2; else if (val >= 200) return 1; else if (val >= 1) return 0.5; else return 0; }, legendHoverLink: true, showEffectOn: "render", rippleEffect: { // period: 4, scale: 6, color: "rgba(255,255,255, 0.6)", brushType: "fill", }, //地图中心点显示样式 label: { show: false, formatter: (params) => { if (params.data) { return params.name + ":" + params.data["value"][2]; } else { return params.name; } }, fontSize: 11, offset: [0, 2], position: "bottom", textBorderColor: "#fff", textShadowColor: "#000", textShadowBlur: 10, textBorderWidth: 0, color: "#47C1BF", }, // colorBy: "data", itemStyle: { color: "rgba(255,255,255,1)", borderColor: "rgba(2255,255,255,2)", borderWidth: 4, shadowColor: "#47C1BF", shadowBlur: 10, } } ] } // 重新选择区域 this.handleMapRandomSelect(); }, // 开启定时器 startInterval() { const _self = this; const time = 3000; if (this.intervalId !== null) { clearInterval(this.intervalId); } this.intervalId = setInterval(() => { _self.reSelectMapRandomArea(); }, time); }, // 重新随机选中地图区域 reSelectMapRandomArea() { this.$nextTick(() => { try { let ref = this.$refs.map if (ref) { const map = ref.chart; let index = Math.floor(Math.random() * this.length); while (index === this.preSelectMapIndex || index >= this.length) { index = Math.floor(Math.random() * this.length); } map.dispatchAction({ type: 'mapUnSelect', seriesIndex: 0, dataIndex: this.preSelectMapIndex, }); map.dispatchAction({ type: 'showTip', seriesIndex: 0, dataIndex: index, }); map.dispatchAction({ type: 'mapSelect', seriesIndex: 0, dataIndex: index, }); this.preSelectMapIndex = index; } } catch (error) { } }); }, handleMapRandomSelect() { this.$nextTick(() => { try { let ref = this.$refs.map if (ref) { const map = ref.chart; const _self = this; setTimeout(() => { _self.reSelectMapRandomArea(); }, 0); // 移入区域,清除定时器、取消之前选中并选中当前 map.on('mouseover', function (params) { clearInterval(_self.intervalId); map.dispatchAction({ type: 'mapUnSelect', seriesIndex: 0, dataIndex: _self.preSelectMapIndex, }); map.dispatchAction({ type: 'mapSelect', seriesIndex: 0, dataIndex: params.dataIndex, }); _self.preSelectMapIndex = params.dataIndex; }); // 移出区域重新随机选中地图区域,并开启定时器 map.on('globalout', function () { _self.reSelectMapRandomArea(); _self.startInterval(); }); this.startInterval(); } } catch (error) { } }); }, } } </script>
common/map.js
内容过长,节选展示
const mapJson={"type":"FeatureCollection","features":[{"type":"Feature","properties":{"adcode":820000,"name":"澳门","center":[113.54909,22.198951],"centroid":[113.566988,22.159307],"childrenNum":8,"level":"province","parent":{"adcode":100000},"subFeatureIndex":33,"acroutes":[100000]},"geometry":{"type":"MultiPolygon","coordinates":[[[[113.554425,22.107489],[113.6037,22.132438],[113.575983,22.194513],[113.558736,22.212244],[113.53841,22.209473],[113.534715,22.174009],[113.554425,22.142416],[113.554425,22.107489]]],[[[113.586453,22.201162],[113.575983,22.201162],[113.575983,22.194513],[113.586453,22.201162]]]]}}]} export default {mapJson}
封装的echart组件echart/index.vue
<template> <div :id="id" :class="className" :style="{ height: height, width: width }" /> </template> <script> import tdTheme from './theme.json' // 引入默认主题 export default { name: 'echart', props: { className: { type: String, default: 'chart' }, id: { type: String, default: 'chart' }, width: { type: String, default: '100%' }, height: { type: String, default: '2.5rem' }, options: { type: Object, default: ()=>({}) } }, data () { return { chart: null } }, watch: { options: { handler (options) { // 设置true清空echart缓存 this.chart.setOption(options, true) }, deep: true } }, mounted () { this.$echarts.registerTheme('tdTheme', tdTheme); // 覆盖默认主题 this.initChart(); }, beforeDestroy () { this.chart.dispose() this.chart = null }, methods: { initChart () { // 初始化echart this.chart = this.$echarts.init(this.$el, 'tdTheme') this.chart.setOption(this.options, true) } } } </script>
theme.json
{ "color": [ "#2d8cf0", "#19be6b", "#ff9900", "#E46CBB", "#9A66E4", "#ed3f14" ], "backgroundColor": "rgba(0,0,0,0)", "textStyle": {}, "title": { "textStyle": { "color": "#516b91" }, "subtextStyle": { "color": "#93b7e3" } }, "line": { "itemStyle": { "normal": { "borderWidth": "2" } }, "lineStyle": { "normal": { "width": "2" } }, "symbolSize": "6", "symbol": "emptyCircle", "smooth": true }, "radar": { "itemStyle": { "normal": { "borderWidth": "2" } }, "lineStyle": { "normal": { "width": "2" } }, "symbolSize": "6", "symbol": "emptyCircle", "smooth": true }, "bar": { "itemStyle": { "normal": { "barBorderWidth": 0, "barBorderColor": "#ccc" }, "emphasis": { "barBorderWidth": 0, "barBorderColor": "#ccc" } } }, "pie": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" }, "emphasis": { "borderWidth": 0, "borderColor": "#ccc" } } }, "scatter": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" }, "emphasis": { "borderWidth": 0, "borderColor": "#ccc" } } }, "boxplot": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" }, "emphasis": { "borderWidth": 0, "borderColor": "#ccc" } } }, "parallel": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" }, "emphasis": { "borderWidth": 0, "borderColor": "#ccc" } } }, "sankey": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" }, "emphasis": { "borderWidth": 0, "borderColor": "#ccc" } } }, "funnel": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" }, "emphasis": { "borderWidth": 0, "borderColor": "#ccc" } } }, "gauge": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" }, "emphasis": { "borderWidth": 0, "borderColor": "#ccc" } } }, "candlestick": { "itemStyle": { "normal": { "color": "#edafda", "color0": "transparent", "borderColor": "#d680bc", "borderColor0": "#8fd3e8", "borderWidth": "2" } } }, "graph": { "itemStyle": { "normal": { "borderWidth": 0, "borderColor": "#ccc" } }, "lineStyle": { "normal": { "width": 1, "color": "#aaa" } }, "symbolSize": "6", "symbol": "emptyCircle", "smooth": true, "color": [ "#2d8cf0", "#19be6b", "#f5ae4a", "#9189d5", "#56cae2", "#cbb0e3" ], "label": { "normal": { "textStyle": { "color": "#eee" } } } }, "map": { "itemStyle": { "normal": { "areaColor": "#f3f3f3", "borderColor": "#516b91", "borderWidth": 0.5 }, "emphasis": { "areaColor": "rgba(165,231,240,1)", "borderColor": "#516b91", "borderWidth": 1 } }, "label": { "normal": { "textStyle": { "color": "#000" } }, "emphasis": { "textStyle": { "color": "rgb(81,107,145)" } } } }, "geo": { "itemStyle": { "normal": { "areaColor": "#f3f3f3", "borderColor": "#516b91", "borderWidth": 0.5 }, "emphasis": { "areaColor": "rgba(165,231,240,1)", "borderColor": "#516b91", "borderWidth": 1 } }, "label": { "normal": { "textStyle": { "color": "#000" } }, "emphasis": { "textStyle": { "color": "rgb(81,107,145)" } } } }, "categoryAxis": { "axisLine": { "show": true, "lineStyle": { "color": "#cccccc" } }, "axisTick": { "show": false, "lineStyle": { "color": "#333" } }, "axisLabel": { "show": true, "textStyle": { "color": "#fff" } }, "splitLine": { "show": false, "lineStyle": { "color": [ "#eeeeee" ] } }, "splitArea": { "show": false, "areaStyle": { "color": [ "rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)" ] } } }, "valueAxis": { "axisLine": { "show": true, "lineStyle": { "color": "#cccccc" } }, "axisTick": { "show": false, "lineStyle": { "color": "#333" } }, "axisLabel": { "show": true, "textStyle": { "color": "#fff" } }, "splitLine": { "show": false, "lineStyle": { "color": [ "#eeeeee" ] } }, "splitArea": { "show": false, "areaStyle": { "color": [ "rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)" ] } } }, "logAxis": { "axisLine": { "show": true, "lineStyle": { "color": "#cccccc" } }, "axisTick": { "show": false, "lineStyle": { "color": "#333" } }, "axisLabel": { "show": true, "textStyle": { "color": "#999999" } }, "splitLine": { "show": true, "lineStyle": { "color": [ "#eeeeee" ] } }, "splitArea": { "show": false, "areaStyle": { "color": [ "rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)" ] } } }, "timeAxis": { "axisLine": { "show": true, "lineStyle": { "color": "#cccccc" } }, "axisTick": { "show": false, "lineStyle": { "color": "#333" } }, "axisLabel": { "show": true, "textStyle": { "color": "#999999" } }, "splitLine": { "show": true, "lineStyle": { "color": [ "#eeeeee" ] } }, "splitArea": { "show": false, "areaStyle": { "color": [ "rgba(250,250,250,0.05)", "rgba(200,200,200,0.02)" ] } } }, "toolbox": { "iconStyle": { "normal": { "borderColor": "#999" }, "emphasis": { "borderColor": "#666" } } }, "legend": { "textStyle": { "color": "#fff" } }, "tooltip": { "axisPointer": { "lineStyle": { "color": "#ccc", "width": 1 }, "crossStyle": { "color": "#ccc", "width": 1 } } }, "timeline": { "lineStyle": { "color": "#8fd3e8", "width": 1 }, "itemStyle": { "normal": { "color": "#8fd3e8", "borderWidth": 1 }, "emphasis": { "color": "#8fd3e8" } }, "controlStyle": { "normal": { "color": "#8fd3e8", "borderColor": "#8fd3e8", "borderWidth": 0.5 }, "emphasis": { "color": "#8fd3e8", "borderColor": "#8fd3e8", "borderWidth": 0.5 } }, "checkpointStyle": { "color": "#8fd3e8", "borderColor": "rgba(138,124,168,0.37)" }, "label": { "normal": { "textStyle": { "color": "#8fd3e8" } }, "emphasis": { "textStyle": { "color": "#8fd3e8" } } } }, "visualMap": { "color": [ "#516b91", "#59c4e6", "#a5e7f0" ] }, "dataZoom": { "backgroundColor": "rgba(0,0,0,0)", "dataBackgroundColor": "rgba(255,255,255,0.3)", "fillerColor": "rgba(167,183,204,0.4)", "handleColor": "#a7b7cc", "handleSize": "100%", "textStyle": { "color": "#333" } }, "markPoint": { "label": { "normal": { "textStyle": { "color": "#eee" } }, "emphasis": { "textStyle": { "color": "#eee" } } } } }
main.js
// 按需引入vue-awesome图标 import Icon from 'vue-awesome/components/Icon'; import 'vue-awesome/icons/map.js'; import dataV from '@jiaminghi/data-view'; import Echart from './common/echart/index.vue' // 全局注册 Vue.component('icon', Icon); Vue.component("Echart", Echart) Vue.use(dataV); //引入echart //4.x 引用方式 //import echarts from 'echarts'; //5.x 引用方式为按需引用 //希望使用5.x版本的话,需要在package.json中更新版本号,并切换引用方式 import * as echarts from 'echarts' //本例使用的是^5.4.0版本 Vue.prototype.$echarts = echarts