深圳幻海软件技术有限公司 欢迎您!

用好 Echart5 绘制地图,让可视化大屏描边酷炫

2023-02-28

可视化我们已不再陌生,地图也很常用。有很多公司业务范围可能仅限于某个市区,所以画一个china地图意义不大,就只需要绘制某个省份或者市区的地图,然后统计各个区域的一个分布情况,具体的效果如图所示:一、实现原理:绘制地图之前,我们先需要明白实现原理是啥样的,然后按照具体的实现步骤,依次实现效果。如果不

可视化我们已不再陌生,地图也很常用。有很多公司业务范围可能仅限于某个市区,所以画一个 china 地图意义不大,就只需要绘制某个省份或者市区的地图,然后统计各个区域的一个分布情况,具体的效果如图所示:

一、实现原理:

绘制地图之前,我们先需要明白实现原理是啥样的,然后按照具体的实现步骤,依次实现效果。如果不明白原理,每次完成的都是复制粘贴。

1、开始之前,先确认自己的地图需要分几层,及其作用。

2、该效果实现,需要三层地图实现效果。

  • 一层放在最底层,设置地图的边框,对应地图里最外层的蓝色地图线。
  • 二层放在中间,实现基本的地图层,显示对应各个区域的名称。
  • 三层放在最外层,实现数据标记,对应地图里圆圈和数据。

3、拖动或缩放的时候出现错位,使其同步缩放和拖动。

二、Echarts 使用五部曲:

1、下载并引入 echarts

Echarts 已更新到了 5.0 版本,安装完记得检查下自己的版本是否是 5.0 。

npm install echarts --save
  • 1.

下载地图的 json 数据。

可以下载中国以及各个省、市、区地图数据。免费的文件下载地址:

http://datav.aliyun.com/portal/school/atlas/area_selector#&lat=30.332329214580188&lng=106.72278672066881&zoom=3.5。

下载对应的省份或者市区的地图数据。

引入:

QQAN" data-card-editable="false" class="" data-syntax="css">
import * as echarts from "echarts"
import chinaJSON from '../../assets/json/china.json'
  • 1.
  • 2.

2、准备容器

给元素定义宽高确定的容器用来装地图。

<template>
 <div ref="xian"></div>  
</template>
  • 1.
  • 2.
  • 3.

3、实例化 echarts 对象

import * as echarts from 'echarts'
import xianJSON from '../../assets/json/xian.json'
const xian = ref()
var myChart = echarts.init(xian.value)
// 创建了一个 myChart 对象
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

如果是绘制的地图,需要先引入和注册地图:

echarts.registerMap('xa', xianJSON)
  • 1.

4、指定配置项和数据

var option = {
 // 存放需要绘制图片类型,以及样式设置
}
  • 1.
  • 2.
  • 3.

5、给 echarts 对象设置配置项

myChart.setOption(option)
  • 1.

三、具体实现步骤

步骤1:绘制基本地图层,显示各个区域。

具体代码为:

<template>
 <div>
  <div ref="xian"
   style="width: 100%;height: 800px;border: solid 1px red;background: #011868;"
  ></div>
 </div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import xianJSON from '../../assets/json/xian.json'
const xian = ref()
onMounted(() => {
 drwaMap()
})
function drwaMap() {
 var myChart = echarts.init(xian.value)
 echarts.registerMap('xa', xianJSON)
 var option = {
  geo: {
   map: 'xa',
   zoom: 1,
   roam: true,
   center: [109.00853, 34.11078],
   label: {
    show: true,
    color: 'rgba(255,255,255,0.2)',
   },
   itemStyle: {
    normal: {
     areaColor: '#080b1a',
     borderColor: 'rgba(0,116,255,0.2)',
     borderWidth: 2,
     borderType: 'dashed',
    },
    emphasis: {
      areaColor: '#4f6ee9',
      color: 'rgba(255,255,255,0.8)',
     },
    },
   },
 }
 myChart.setOption(option)
}
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.

步骤2:底层绘制一个地图层,设置地图外层边框。

添加 series 属性,再绘制一个地图层,利用 z 放到最底层。

series: [
 //绘制一个新地图
 {
  type: 'map',
  map: 'xa',
  zoom: 1,
  roam: true,
  center: [109.00853, 34.11078],
  z: -1, // 置于底层
  itemStyle: {
   normal: {
    areaColor: '#2e488f',
    borderColor: '#0074ff',
    borderWidth: 5,//设置外层边框线粗细
   },
  },
 },
],
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

步骤3:添加分布的数据点标记。

给 series 中再添加一个配置项:

{
 type: 'effectScatter', // 特效散点图
 coordinateSystem: 'geo',
 symbol: 'circle',
 // symbolSize 设置标记点的大小,
 //把大小限制再 30 - 50 之间
 symbolSize: function (val) {
  return 30 + (val[2] / 100) * 20
 },
 colorBy: 'series',
 //显示name并设置样式
 label: {
  show: true,
  formatter: function (data) {
   return data.value[2]
  },
  color: '#080b1a',
  fontSize: '16',
  offset: [0, 0],
  align: 'center',
  },
  //涟漪效果设置
 rippleEffect: {
  color: '#32479d',
  number: 3,
  period: 4,
  scale: 2,
  brushType: 'stroke',
 },
 itemStyle: {
  normal: {
  color: '#00e6ff',
  borderColor: '#32479d',
  borderWidth: 2,
 },
 },
 data: [
  { name: '蓝田', value: [109.423479, 34.181634, 50] },
  { name: '长安区', value: [108.923479, 34.110134, 30] },
  { name: '周至县', value: [108.123479, 34.010134, 2] },
  { name: '鄠邑区', value: [108.573479, 34.100134, 4] },
  { name: '临潼区', value: [109.283479, 34.510134, 3] },
  { name: '高陵区', value: [109.059479, 34.550134, 1] },
 ],
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.

步骤4:处理放大缩小时不同步的问题。

捕捉 georoam 事件,上层的 geo 缩放、偏移的时候,让下层的 map 跟着上层同步进行。添加代码:

myChart.on('georoam', function (params) {
 var option = myChart.getOption() //获得option对象
 if (params.zoom != null && params.zoom != undefined) {
  //捕捉到缩放时
  option.series[0].zoom = option.geo[0].zoom //下层geo的缩放等级跟着上层的geo一起改变
  option.series[0].center = option.geo[0].center //下层的geo的中心位置随着上层geo一起改变
 } else {
 //捕捉到拖曳时
  option.series[0].center = option.geo[0].center //下层的geo的中心位置随着上层geo一起改变
 }
 myChart.setOption(option) //设置option
})
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

四、完整源码

<template>
  <div>
    <div
      ref="xian"
      style="
        width: 100%;
        height: 800px;
        border: solid 1px red;
        background: #0c0b2a;
      "
    ></div>
  </div>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import xianJSON from '../../assets/json/xian.json'
const xian = ref()
onMounted(() => {
  drwaMap()
})
function drwaMap() {
  var myChart = echarts.init(xian.value)
  echarts.registerMap('xa', xianJSON)
  var option = {
    geo: {
      map: 'xa',
      zoom: 1,
      roam: true,
      center: [109.00853, 34.11078],
      label: {
        show: true,
        color: 'rgba(255,255,255,0.2)',
      },
      itemStyle: {
        normal: {
          areaColor: '#080b1a',
          borderColor: 'rgba(0,116,255,0.2)',
          borderWidth: 2,
          borderType: 'dashed',
        },
        emphasis: {
          areaColor: '#4f6ee9',
          color: 'rgba(255,255,255,0.8)',
        },
      },
    },
    series: [
      //绘制一个新地图
      {
        type: 'map',
        map: 'xa',
        zoom: 1,
        roam: true,
        center: [109.00853, 34.11078],
        z: -1,
        itemStyle: {
          normal: {
            areaColor: '#2e488f',
            borderColor: '#0074ff',
            borderWidth: 5,
          },
        },
      },
      {
        type: 'effectScatter', // 特效散点图
        coordinateSystem: 'geo',
        symbol: 'circle',
        symbolSize: function (val) {
          return 30 + (val[2] / 100) * 20
        },
        colorBy: 'series',
        //显示name并设置样式
        label: {
          show: true,
          formatter: function (data) {
            return data.value[2]
          },
          color: '#080b1a',
          fontSize: '16',
          offset: [0, 0],
          align: 'center',
        },
        //涟漪效果设置
        rippleEffect: {
          color: '#32479d',
          number: 3,
          period: 4,
          scale: 2,
          brushType: 'stroke',
        },
        itemStyle: {
          normal: {
            color: '#00e6ff',
            borderColor: '#32479d',
            borderWidth: 2,
          },
        },
        data: [
          { name: '蓝田', value: [109.423479, 34.181634, 50] },
          { name: '长安区', value: [108.923479, 34.110134, 30] },
          { name: '周至县', value: [108.123479, 34.010134, 2] },
          { name: '鄠邑区', value: [108.573479, 34.100134, 4] },
          { name: '临潼区', value: [109.283479, 34.510134, 3] },
          { name: '高陵区', value: [109.059479, 34.550134, 1] },
        ],
      },
    ],
  }
  myChart.setOption(option)
  // 同步缩放、偏移
  myChart.on('georoam', function (params) {
    var option = myChart.getOption() //获得option对象
    if (params.zoom != null && params.zoom != undefined) {
      //捕捉到缩放时
      option.series[0].zoom = option.geo[0].zoom //下层geo的缩放等级跟着上层的geo一起改变
      option.series[0].center = option.geo[0].center //下层的geo的中心位置随着上层geo一起改变
    } else {
      //捕捉到拖曳时
      option.series[0].center = option.geo[0].center //下层的geo的中心位置随着上层geo一起改变
    }
    myChart.setOption(option) //设置option
  })
}
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.