echarts矢量地图自定义图标数据展示—echarts地图图表三种方案
Author:[email protected] Date:
地图数据展示,最先开始是想用百度地图,自定义覆盖物的形式展现,但是无法要做到区域选择高亮,还是比较麻烦。echarts可以实现矢量地图,地图图表并配上大数据。但是,需要把数据自定义形式覆盖到 地图上去。地图的formatter需要手工定义。
echarts地图图表三种方案
第一种方案,直接用地图图表形式展现
import echarts from 'echarts' import shenZhenArea from 'shenZhen-area' //区域gis数据,区域 properties 属性里面没有cp 属性(lable),自动计算,可有手动补上。 import shenZhenBorder from 'shenZhen-border.json'边界gis数据,方便实现自定义外边框 //地图展示数据 let mapData2ShowValue = [ {"name": "光明区", "value": [2121, 1800]}, {"name": "南山区", "value": [2121, 1800]}, {"name": "盐田区", "value": [2121, 1800]}, {"name": "罗湖区", "value": [2121, 1800]}, {"name": "福田区", "value": [2121, 1800]}, {"name": "大鹏新区", "value": [2121, 1800]}, {"name": "龙岗区", "value": [2121, 1800]}, {"name": "坪山区", "value": [2121, 1800]}, {"name": "宝安区", "value": [2121, 1800]}, {"name": "龙华区", "value": [2121, 1800]}] echarts.registerMap('shenZhenBorder', shenZhenBorder) echarts.registerMap('shenZhenArea', shenZhenArea) let chart1 = echarts.init(document.getElementById('map1')) chart1.setOption({ geo: { type: 'map', map: 'shenZhenBorder', itemStyle: { areaColor: '#f0f', borderColor: '0ff', //省市边界线 borderWidth: 4, }, label: { show: false, }, emphasis: { itemStyle: { areaColor: "rgba(0,193,255,0)", }, } }, series: [ { name: 'name4', type: 'map', mapType: 'shenZhenArea', data: mapData2ShowValue, // nameMap: nameMap,//label 用了 formatter ,所以需要注释 selectedMode: 'false', //是否允许选中多个区域 itemStyle: { areaColor: "rgba(0,51,100,.4)", borderColor: "rgba(0,150,236,1)", }, label: { show: true, width: 110, height: 110, align: 'left', position: [0, 0], backgroundColor: { image: require('../../../public/maps/map-icon2.png'), width: 110, height: 110 }, formatter: function (val) { // console.log('_______-formatter') // console.log(val) let str= '{a|' + (nameMap&&nameMap[val.name]||val.name) + '}' + '\n' + '{hr|}\n' // + '{num|' + val.data.value[0] + '}\n' // + '{num|' + val.data.value[1] + '}' //可能有多个数值 let numArr=val.data.value.map(num=>{ return '{num|' + num + '}' }) str+=numArr.join('\n') return str; }, rich: { a: { color: '#000', fontSize: 14, padding: [0, 0, 15, 10], align: 'left', }, hr: { width: 110, height: 30, }, num: { padding: [8, 0, 0, 35], color: '#fff', fontSize: 14, } }, }, emphasis: { itemStyle: { areaColor: "rgba(0,193,255,.6)", }, }, }, ] })
如果需要改动标注点的位置,需要改变cp坐标
//设置区域 标注地点,默认echarts自动计算 shenZhenArea.features.forEach((area, index) => { area.properties['cp'] = scatterData[index].value.slice(0,2) }) //地图名字区域实际名字 和 自定义地区的名称映射 let nameMap = {} mapData2ShowValue.forEach((item, index) => { nameMap[item.name]=scatterData[index].name })
第二方案,通过散点,添加上去
import echarts from 'echarts' import shenZhenArea from 'shenZhen-area' import shenZhenBorder from 'shenZhen-border.json'边界gis数据,方便实现自定义外边框 echarts.registerMap('shenZhenBorder', shenZhenBorder) echarts.registerMap('shenZhenArea', shenZhenArea) let chart2 = echarts.init(document.getElementById('map2')) //散点 添加标注到地图 series data 数据 let scatterData = [ { "name": "光明", "value": [113.92635602317334, 22.77565238823337, 2121, 1800] }, { "name": "南山", "value": [113.90793997084684, 22.49941161039266, 2121, 1800] }, { "name": "盐田", "value": [114.26956427107639, 22.59860716243546, 2121, 1800] }, { "name": "罗湖", "value": [114.14902283766655, 22.56721616495356, 2121, 1800] }, { "name": "福田", "value": [114.04857164315834, 22.547125926565144, 2121, 1800] }, { "name": "大鹏", "value": [114.48218596611878, 22.607396641730393, 2121, 1800] }, { "name": "龙岗", "value": [114.25617077847531, 22.73296063165799, 2121, 1800] }, { "name": "坪山", "value": [114.35829615955865, 22.677712476089848, 2121, 1800] }, { "name": "宝安", "value": [113.85938856016787, 22.64632147860795, 2121, 1800] }, { "name": "龙华", "value": [114.04187489685779, 22.7116147533703, 2121, 1800] }]; chart2.setOption({ geo: { map: 'shenZhenBorder', itemStyle: { areaColor: "rgba(0,139,255,0)", borderColor: "rgba(0,150,236,1)", //省市边界线 borderWidth: 4, }, emphasis: { itemStyle: { areaColor: "rgba(0,193,255,0)", }, } }, series: [ { tooltip: { show: false, }, type: 'map', map: 'shenZhenArea', itemStyle: { areaColor: "rgba(0,51,100,.4)", borderColor: "rgba(0,150,236,1)", }, label: { show: false, }, emphasis: { itemStyle: { areaColor: "rgba(0,193,255,.6)", }, label: { show: false, }, } }, { name: 'ShowData', type: 'scatter', coordinateSystem: 'geo', // symbol:'none', symbol: `image://${require('../../../public/maps/map-icon2.png')}`, symbolSize: [110, 110], encode: { value: 2 }, label: { show: true, width: 110, height: 110, align: 'left', position: [0, 0], formatter: function (val) { // console.log('_______-formatter') // console.log(val) let str= '{a|' + (nameMap&&nameMap[val.name]||val.name) + '}' + '\n' + '{hr|}\n' // + '{num|' + val.data.value[0] + '}\n' // + '{num|' + val.data.value[1] + '}' //可能有多个数值 let temArr=val.data.value.slice(2) let numArr=temArr.map(num=>{ return '{num|' + num + '}' }) str+=numArr.join('\n') return str; }, rich: { a: { color: '#000', fontSize: 14, padding: [0, 0, 15, 10], align: 'left', }, hr: { width: 110, height: 30, }, num: { padding: [8, 0, 0, 60], color: '#fff', fontSize: 14, }, num2: { fontSize: 14, } }, //富文本样式,就是上面的formatter中'{a|'和'{b|' }, /*label: { show: true, position: ['0', '15%'], formatter: function(val) { // console.log('val') /!* let dom= ''+ ''+ ''+val.name+''+ ''+ ''+ ''+val.data.value[2]+''+ ''+val.data.value[3]+''+ ''+ '' return dom;*!/ // console.log(val) return '{name|' + val.name + '}' + '\n' +'{hr|}\n' + '{yellow|}{b|' + val.data.value[2] +'}\n' + '{blue|}{b|' + val.data.value[3]+ '}'; }, //让series 中的文字进行换行 rich: { name: { color: '#000', fontSize: 14, }, hr:{ width:80, height:30 }, yellow:{ verticalAlign:'middle', offset:[-30,0], width:8, height:8, backgroundColor:'#fff22a', borderRadius:8, }, blue:{ verticalAlign:'middle', // offset:[30,0], width:8, height:8, backgroundColor:'#2813ff', borderRadius:8, }, abg: { backgroundColor: '#033', width: '100%', align: 'right', height: 25, padding:[0,10], borderRadius: [4, 4, 0, 0] }, b: { color: '#fff', fontFamily: 'Microsoft YaHei', fontSize: 14, width: '100%', height: 24, padding:[0,10], backgroundColor: 'rgba(4,4,4,0.5)', borderRadius: 4, // borderWidth: 1, // borderColor: '#f00', textAlign: 'center', } }, //富文本样式,就是上面的formatter中'{a|'和'{b|' },*/ itemStyle: { normal: { color: '#f4e925', shadowBlur: 10, shadowColor: '#333' } }, data: scatterData, } ] })
第三种方案,通过获取标注点的经纬度转像素坐标,绝对定位dom到地图上,通过css 鼠标事件穿透,pointer-events: none。等等手段达到目的
import echarts from 'echarts' import shenZhenArea from 'shenZhen-area' import shenZhenBorder from 'shenZhen-border.json' echarts.registerMap('shenZhenBorder', shenZhenBorder) echarts.registerMap('shenZhenArea', shenZhenArea) let chart3 = echarts.init(document.getElementById('map3')) let scatterData = [ { "name": "光明", "value": [113.92635602317334, 22.77565238823337, 2121, 1800] }, { "name": "南山", "value": [113.90793997084684, 22.49941161039266, 2121, 1800] }, { "name": "盐田", "value": [114.26956427107639, 22.59860716243546, 2121, 1800] }, { "name": "罗湖", "value": [114.14902283766655, 22.56721616495356, 2121, 1800] }, { "name": "福田", "value": [114.04857164315834, 22.547125926565144, 2121, 1800] }, { "name": "大鹏", "value": [114.48218596611878, 22.607396641730393, 2121, 1800] }, { "name": "龙岗", "value": [114.25617077847531, 22.73296063165799, 2121, 1800] }, { "name": "坪山", "value": [114.35829615955865, 22.677712476089848, 2121, 1800] }, { "name": "宝安", "value": [113.85938856016787, 22.64632147860795, 2121, 1800] }, { "name": "龙华", "value": [114.04187489685779, 22.7116147533703, 2121, 1800] }]; chart3.setOption({ geo: { map: 'shenZhenBorder', itemStyle: { areaColor: "rgba(0,139,255,0)", borderColor: "rgba(0,150,236,1)", //省市边界线 borderWidth: 4, }, emphasis: { itemStyle: { areaColor: "rgba(0,193,255,0)", }, } }, series: [ { tooltip: { show: false, }, type: 'map', map: 'shenZhenArea', itemStyle: { areaColor: "rgba(0,51,100,.4)", borderColor: "rgba(0,150,236,1)", }, label: { show: false, }, // data:shenZhenArea.features.map((area)=>{ // return area.properties.name // }), emphasis: { itemStyle: { areaColor: "rgba(0,193,255,.6)", }, label: { show: false, }, } }, ] }) let chartBox3 = this.$refs.chartBox3 setMapMark(chartBox3) function setMapMark(box) { let domList = scatterData.map((item) => { let arrPx = chart3.convertToPixel('geo', item.value.slice(0, 2)) let temArr=item.value.slice(2) // console.log(arrPx) let dom = ` ${item.name} ${temArr.map((num)=>{ //可能有多个数值 return ` ${num} ` }).join('')} ` return dom }) box.innerHTML = domList.join('') }
dom样式
.map-item-show { z-index: 99999; position: absolute; width: 109px; height: 110px; font-size: 14px; background: url('../../../public/maps/map-icon.png') no-repeat; background-size: 44px 100px; line-height: 1; pointer-events: none; } .map-name-box { color: #000; padding: 14px 8px; } .map-data-box { width: 56px; background: rgba(0, 0, 0, .4); border-radius: 4px; color: #fff; padding :2px 8px; margin :10px 0 0 30px; >div{ line-height :18px; display :flex; justify-content :start; align-items :center; } .map-data-icon{ width :8px; height :8px; background :#2813ff; border-radius :100%; margin-right :6px; } .icon-yellow{ background #fff22a; } }
三面三种方案都可以实现各有优劣,第一实现最简单,第二种实现map 于散点复合图表,可以做出效果更佳
第三种dom实现,免得写坑爹的formatter(rich没有css3来的顺手)
搞完也累了,给个美女,看看
转载本站文章《echarts矢量地图自定义图标数据展示—echarts地图图表三种方案》,
请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/js/2016_0219_7633.html