以前写过 vue项目中封装echarts的比较优雅的方式,vue2项目中封装echarts地图比较优雅的方式,这次对地图做一个小拓展,在vue2项目中封装echarts地图比较优雅的方式 的基础上进行。
能学到的知识
1、ECharts地图背景图设置,可以设置随意的地图纹理
2、echarts地图打点,显示数据
效果图
虽然不明显,但是打点是真的在闪动的
实现
在 vue2项目中封装echarts地图比较优雅的方式 的基础上稍微做点改变。
echarts地图模块封装
|-- src |-- components |-- chart |-- options // 存放各种图表的option |-- map // 地图option |-- index.js
具体代码如下:
// import echarts from 'echarts'import * as echarts from 'echarts'import mapbg from '@/assets/images/map-bg.png'const getSimpleMap = (jsonMap, data, config) => { if (!echarts.getMap(jsonMap.mark)) { echarts.registerMap(jsonMap.mark, jsonMap.json) } const convertData = (data) => { console.log(data) var res = [] for (var i = 0; i < data.length; i++) { const mapData = data[i].hoverObj const center = data[i].mapProperty.center if (center && mapData) { res.push({ name: mapData.name, value: center.concat(mapData.num) }) } } return res } const defaultConfig = { tooltip: { // 窗口外框 trigger: 'item', padding: 0, borderWidth: 0, borderColor: '#FFFFFF', backgroundColor: '#FFFFFF', formatter: (params) => { const { data } = params const str = `<div style="width:300px;height: 98px;box-shadow: 0px 4px 20px 0px rgba(0, 0, 0, 0.8); color: #fff;text-align:left;border-radius: 6px;"> <div style="background-color: rgba(102, 182, 255, 1);height: 44px;line-height: 44px;font-size:14px;font-weight:400;border-top-left-radius: 6px;border-top-right-radius: 6px;display: flex;align-items: center;"> <img style="width: 13px;height:16px;margin-left: 24px;margin-right: 3px;" src="images/map-ic.png">${data.name} </div> <div style="width: 100%;height:54px;display: flex;flex-wrap: wrap;"> <div style="display: flex;justify-content: space-between;width: 100%;padding-left:15px;padding-right: 15px;"> <div style="display:flex;align-items:center;width:132px;"> <div style="font-size: 12px;color: #555555;margin-right:10px;">区号:</div> <div style="font-size: 14px;color: #333333;">${data.hoverObj == null ? '' : data.hoverObj.adcode}</div> </div> </div> </div> </div>` return str } }, geo: { map: jsonMap.mark, type: 'map', layoutCenter: ['50%', '50%'], layoutSize: '150%', zoom: 0.65, roam: false, // 样式一 // itemStyle: { // normal: { // areaColor: 'rgba(13, 110, 191, 1)', // shadowColor: 'rgba(13, 110, 191, 0.5)', // shadowOffsetX: 6, // shadowOffsetY: 12 // } // } // 样式二 itemStyle: { normal: { borderColor: '#AEF3FF', borderWidth: 2, areaColor: { image: mapbg, // repeat: 'repeat' // // 是否平铺,可以是 'repeat-x', 'repeat-y', 'no-repeat' }, shadowColor: 'rgba(13, 110, 191, 0.5)', shadowOffsetX: 6, shadowOffsetY: 12 } } }, series: [ { type: 'map', map: jsonMap.mark, // 自定义扩展图表类型 zoom: 0.65, // 缩放 animationDuration: 1200, // 点击选中后的效果 select: { label: { color: '#FFFFFF', fontSize: 12, fontWeight: 400 }, // 清除点击选中后的背景色 itemStyle: { color: null } }, // 样式一 // itemStyle: { // // 地图样式 // normal: { // borderColor: '#FFFFFF', // borderWidth: 3, // areaColor: 'rgba(201, 229, 255, 1)' // } // }, // 样式二 itemStyle: { // 地图样式 normal: { borderColor: '#AEF3FF', borderWidth: 2, areaColor: { image: mapbg, // repeat: 'repeat' // // 是否平铺,可以是 'repeat-x', 'repeat-y', 'no-repeat' } } }, // 样式一 // label: { // show: true, // color: '#666666', // fontSize: 12, // fontWeight: 400 // }, // 样式二 label: { show: true, color: '#FFFFFF', fontSize: 12, fontWeight: 400 }, emphasis: { // 鼠标移入动态的时候显示的默认样式 label: { show: true, color: '#FFFFFF', fontSize: 15, fontWeight: 600 }, itemStyle: { areaColor: 'rgba(102, 182, 255, 0.7)', borderColor: '#FFFFFF', borderWidth: 2 } }, layoutCenter: ['50%', '50%'], layoutSize: '150%', data: data }, { type: 'effectScatter', coordinateSystem: 'geo', symbol: 'image://data:image/png;base64,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', symbolSize: [16, 16], // symbolOffset: [], label: { normal: { show: true, offset: [0, -18], textStyle: { color: '#fff', fontSize: 12, fontWeight: 500 }, formatter(value) { return '{a|' + value.data.value[2] + '}' }, rich: { a: { color: '#FFFFFF', backgroundColor: '#06406A', width: 28, height: 16, lineHeight: 16, align: 'center', borderWidth: 1, borderColor: '#79D6FE', borderRadius: 2, padding: [0, 4, 0, 4] } } } }, itemStyle: { normal: { color: 'rgba(255, 178, 76, 1)' } }, data: convertData(data), showEffectOn: 'render', rippleEffect: { brushType: 'stroke' }, hoverAnimation: true, zlevel: 9 } ] } const opt = Object.assign({}, defaultConfig, config) const { legend, tooltip, series, geo, grid } = opt const chartOpt = { grid, legend, tooltip, geo, series } return chartOpt}export default { getSimpleMap}
新增的代码,最好在Visual Studio Code
的Timeline
里面对比查看,只是添加了地图纹理和地图打点。
地图纹理 (components--chart--options--map--index.js)
实现代码在:
geo
样式二的itemStyle
,这里控制鼠标移入地图模块时的纹理
series
样式二的itemStyle
,这里控制地图默认状态下的纹理
地图打点 (components--chart--options--map--index.js)
实现代码在effectScatter
模块,主要是自定义了打点的图标,还有自定义了显示信息的label
的样式,这里可以根据设计随意实现。
打点数据在convertData
方法里面处理,可以根据接口数据看着办。
数据 (views--echartMapTest--index.js)
因为要在地图上打点,需要坐标,加载数据的时候,需要加上地图的坐标,主要是加上这一行,properties
包含了地图所有基本数据了
mapProperty: item.properties
具体如下:
initMap(url) { mapRequest(url).then((res) => { const mapData = res.data const jsonMap = { mark: this.mapName, json: mapData } const data = mapData.features.map((item) => { const { name, adcode } = item.properties let hoverObj = {} const objIndex = this.$utils.findElem(this.mapPopData, 'adcode', adcode) if (objIndex !== -1) { hoverObj = this.mapPopData[objIndex] } else { hoverObj = null } return { name, mapProperty: item.properties, hoverObj: hoverObj } }) this.mapOpt = this.$eChartFn.getSimpleMap(jsonMap, data) }).catch((err) => { console.log(err, '加载地图失败') }) }
代码总览
涉及的文件如下(具体参考代码
):
|-- public |-- data |-- 4401.json |-- mapdata.json|-- src |-- api |-- map.js // 获取地图geojson数据、地图弹窗接口模拟数据 |-- components |-- chart |-- index.vue // 图表单文件组件,供界面调用 |-- index.js // 实现自动化导入options里的图表option |-- options // 存放各种图表的option |-- map // 地图option |-- index.js |-- views |-- echartMapTest // 实例所在 |-- index.vue |-- index.scss |-- index.js |-- utils |---utils.js|-- main.js // 全局引入echarts图表
代码
按代码总览
的目录去代码里找着看就行了。
总结
echarts
地图的纹理不只可以纯色或者渐变色的,还可以根据设计随意设置。项目中UI设计的很好看,这里只是随意截取了纹理的一部分做了个例子。
以上,基本只要UI设计的出来,就可以实现任意纹理样式的地图。
原文;https://juejin.cn/post/7097136735963840542