首页 > webfront > ECMAS > js > > 正文

echarts矢量地图自定义图标数据展示—echarts地图图表三种方案

发布人:zhoulujun@live.cn    点击:

地图数据展示,最先开始是想用百度地图,自定义覆盖物的形式展现,但是无法要做到区域选择高亮,还是比较麻烦。echarts可以实现矢量地图,

地图数据展示,最先开始是想用百度地图,自定义覆盖物的形式展现,但是无法要做到区域选择高亮,还是比较麻烦。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来的顺手)

搞完也累了,给个美女,看看