• Vue3 + Echarts 5 绘制带有立体感流线中国地图,建议收藏


    本文绘制的地图效果图如下:

    Vue3 + Echarts 5 绘制带有立体感流线中国地图,建议收藏

     

    一、Echarts 使用五部曲

    1、下载并引入 echarts

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

    npm install echarts --save

    下载地图的 json 数据

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

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

    记得收藏哦!免得浪费加班时间。

    引入:

    import * as echarts from "echarts"
    import chinaJSON from '../../assets/json/china.json'

     

    2、准备容器

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

    <template>
     <div id="chinaMap"></div>  
    </template>

     

    3、实例化 echarts 对象

    import * as echarts from 'echarts'
    import chinaJson from '../../assets/json/china.json'
    var myChart = echarts.init(document.getElementById('chinaMap'))
    // 创建了一个 myChart 对象

     

    4、指定配置项和数据

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

     

    5、给 echarts 对象设置配置项

    myChart.setOption(option)

     

    Vue3 + Echarts 5 绘制带有立体感流线中国地图,建议收藏

     

    就这么简单几步还用你告诉我吗?不瞒你说,官网也有这东东。虽然这些你都知道,但是并不影响你还是不知道流线图是怎么绘制出来的。下面我们看看是如何绘制的。

    二、开始绘制流线中国地图

    第一步:先绘制一个中国地图

    Vue3 + Echarts 5 绘制带有立体感流线中国地图,建议收藏

     

    复制代码
    import * as echarts from 'echarts'
    import chinaJson from '../../assets/json/china.json'
    import { onMounted, ref } from 'vue'
    const chinaMap = ref()
    onMounted(() => {
     drawChina()
    })
    function drawChina() {
     var myChart = echarts.init(chinaMap.value)
     echarts.registerMap('china', chinaJson) //注册可用的地图
     var option = {
      geo: {
       show: true,
       //设置中心点
       center: [105.194115019531, 35.582111640625],
       map: 'china',
       roam: true, //是否允许缩放,拖拽
       zoom: 1, //初始化大小
       //缩放大小限制
       scaleLimit: {
        min: 0.1, //最小
        max: 12, //最大
       },
       //各个省份模块样式设置
       itemStyle: {
        normal: {
         areaColor: '#3352c7',//背景色
         color: 'red',//字体颜色
         borderColor: '#5e84fd',
         borderWidth: 2,
        },
       },
       //高亮状态
       emphasis: {
        itemStyle: {
         areaColor: '#ffc601',
        },
        label: {
         show: true,
         color: '#fff',
        },
       },
       // 显示层级
       z: 10,
      },
     }
     myChart.setOption(option)
    }
    复制代码

     

    一个简单的地图就绘制好了,继续研究如何添加流线。

    第二步:添加流线

    通过 series 属性来设置发色点的样式,接受点的样式,以及线条和线条上的动画。

    设置 series 的值:

    复制代码
    // 中国地理坐标图
    var chinaGeoCoordMap: Object = {
     西安: [108.906866, 34.162109],
     拉萨: [91.140856, 29.645554],
    }
    //发射点
    var chinaDatas = [
     [
      {
       name: '拉萨',
       value: 2,
      },
     ],
    ]
    //投射点
    const scatterPos = [108.906866, 34.162109]
    // 数据转换
    var convertData = function (data: any) {
     var res = []
     for (var i = 0; i < data.length; i++) {
      var dataItem = data[i]
      var fromCoord = chinaGeoCoordMap[dataItem[0].name]
      var toCoord = scatterPos
      if (fromCoord && toCoord) {
       res.push([
        {
         coord: fromCoord,
         value: dataItem[0].value,
        },
        {
         coord: toCoord,
         },
        ])
      }
     }
     return res
    }
    
    var series: Array<any> = []
    ;[['西安', chinaDatas]].forEach(function (item, i) {
     series.push(
      //设置指向箭头信息
      {
       type: 'lines',
       zlevel: 2,
       effect: {
        show: true,
        period: 4, //箭头指向速度,值越小速度越快
        trailLength: 0.02, //特效尾迹长度[0,1]值越大,尾迹越长重
        symbol: 'arrow', //箭头图标
        symbolSize: 8, //图标大小
       },
       lineStyle: {
        normal: {
         color: '#adffd0',
         width: 1, //尾迹线条宽度
         opacity: 1, //尾迹线条透明度
         curveness: 0.3, //尾迹线条曲直度
        },
       },
       data: convertData(item[1]),
      },
     // 发射点位置涟漪等效果
     {
      type: 'effectScatter',
      coordinateSystem: 'geo',
      zlevel: 2,
      rippleEffect: {
      //涟漪特效
      period: 4, //动画时间,值越小速度越快
      brushType: 'stroke', //波纹绘制方式 stroke, fill
      scale: 4, //波纹圆环最大限制,值越大波纹越大
      },
      label: {
       normal: {
       show: true,
       position: 'right', //显示位置
       offset: [5, 0], //偏移设置
       formatter: function (params) {
        //圆环显示文字
        return params.data.name
       },
       fontSize: 13,
      },
      emphasis: {
       show: true,
      },
     },
     symbol: 'circle',
     symbolSize: function (val: Array<any>) {
      return 5 + val[2] * 5 //圆环大小
     },
     itemStyle: {
     normal: {
      show: false,
      color: '#f8f9f5',
      },
     },
     data: item[1].map(function (dataItem: any) {
      return {
       name: dataItem[0].name,
       value: chinaGeoCoordMap[dataItem[0].name].concat([dataItem[0].value]),
       }
      }),
     },
     //被攻击点
     {
      type: 'effectScatter',
      coordinateSystem: 'geo',
      zlevel: 2,
      rippleEffect: {
       //涟漪相关
       period: 2,
       brushType: 'stroke',
       scale: 5,
       },
      label: {
       normal: {
        show: true,
        position: 'right',
        color: '#0f0',
        formatter: '{b}',
        textStyle: {
         color: '#fff',
         fontSize: 12,
         },
        },
        emphasis: {
         show: true,
         color: '#f60',
        },
       },
       itemStyle: {
        normal: {
        color: '#f00',
       },
      },
      symbol: 'circle',
      symbolSize: 10, //圆圈大小
      data: [
       {
        name: item[0],
        value: chinaGeoCoordMap[item[0]].concat([10]),
        },
       ],
      },
     )
    })
    复制代码

     

    给上边的 option 添加 series 属性。

    第三步:添加立体投影

    添加立体投影的时候,由于并没有这样的属性,所以需要通过设置边框投影,再加一个偏移。

    实现原理:绘制两个地图,设置中心点是一样的,然后一个设置边框投影+偏移,它的层级设置小一点,上边再绘制一个地图不设置投影,这样就能够实现上述效果。

    复制代码
    // series 添加一个对象,绘制新地图
    {
     //绘制一个新地图
     type: 'map',
     map: 'china',
     zoom: 1,
     center: [105.194115019531, 35.582111640625],
     z: -1,
     aspectScale: 0.75, //
     itemStyle: {
      normal: {
       areaColor: '#f00',
       borderColor: '#090438',
       borderWidth: '2',
       shadowColor: '#090438',
       shadowOffsetX: 0,
       shadowOffsetY: 15,
       },
     },
    }
    复制代码

     

    上述效果的完整源码:

    复制代码
    <template>
      <div>
        首页
        <div
          ref="chinaMap"
          class="chinaMap"
          style="
            height: 800px;
            border: solid 1px red;
            width: 100%;
            background: #0b0873;
          "
        >
          地图1
        </div>
      </div>
    </template>
    <style scoped>
    .chinaMap {
      transform: rotate3d(1, 0, 0, 35deg);
    }
    </style>
    <script lang="ts" setup>
    import * as echarts from 'echarts'
    import chinaJson from '../../assets/json/china.json'
    import { onMounted, ref } from 'vue'
    const chinaMap = ref()
    onMounted(() => {
      drawChina()
    })
    /**************************** series start ************************************/
    //中国地理坐标图
    var chinaGeoCoordMap: Object = {
      西安: [108.906866, 34.162109],
      柯桥区: [120.476075, 30.078038],
      拉萨: [91.140856, 29.645554],
      沈阳: [123.431474, 41.805698],
      新疆: [87.627704, 43.793026],
      台湾: [121.508903, 25.044319],
    }
    var chinaDatas = [
      [
        {
          name: '柯桥区',
          value: 0,
        },
      ],
      [
        {
          name: '拉萨',
          value: 2,
        },
      ],
      [
        {
          name: '沈阳',
          value: 1,
        },
      ],
      [
        {
          name: '新疆',
          value: 1,
        },
      ],
      [
        {
          name: '台湾',
          value: 1,
        },
      ],
    ]
    //设置投射点
    const scatterPos = [108.906866, 34.162109]
    
    var convertData = function (data: any) {
      var res = []
      for (var i = 0; i < data.length; i++) {
        var dataItem = data[i]
        var fromCoord = chinaGeoCoordMap[dataItem[0].name]
        var toCoord = scatterPos
        if (fromCoord && toCoord) {
          res.push([
            {
              coord: fromCoord,
              value: dataItem[0].value,
            },
            {
              coord: toCoord,
            },
          ])
        }
      }
      console.log('res', res)
      return res
    }
    
    var series: Array<any> = []
    ;[['西安', chinaDatas]].forEach(function (item, i) {
      console.log(item, item[0])
      series.push(
        {
          //绘制一个新地图
          type: 'map',
          map: 'china',
          zoom: 1,
          center: [105.194115019531, 35.582111640625],
          z: -1,
          aspectScale: 0.75, //
          itemStyle: {
            normal: {
              areaColor: '#f00',
              borderColor: '#090438',
              borderWidth: '2',
              shadowColor: '#090438',
              shadowOffsetX: 0,
              shadowOffsetY: 15,
            },
          },
        },
        //设置指向箭头信息
        {
          type: 'lines',
          zlevel: 2,
          effect: {
            show: true,
            period: 4, //箭头指向速度,值越小速度越快
            trailLength: 0.02, //特效尾迹长度[0,1]值越大,尾迹越长重
            symbol: 'arrow', //箭头图标
            symbolSize: 8, //图标大小
          },
          lineStyle: {
            normal: {
              color: '#adffd0',
              width: 1, //尾迹线条宽度
              opacity: 1, //尾迹线条透明度
              curveness: 0.3, //尾迹线条曲直度
            },
          },
          data: convertData(item[1]),
        },
        // 发射点位置涟漪等效果
        {
          type: 'effectScatter',
          coordinateSystem: 'geo',
          zlevel: 2,
          rippleEffect: {
            //涟漪特效
            period: 4, //动画时间,值越小速度越快
            brushType: 'stroke', //波纹绘制方式 stroke, fill
            scale: 4, //波纹圆环最大限制,值越大波纹越大
          },
          label: {
            normal: {
              show: true,
              position: 'right', //显示位置
              offset: [5, 0], //偏移设置
              formatter: function (params) {
                //圆环显示文字
                return params.data.name
              },
              fontSize: 13,
            },
            emphasis: {
              show: true,
            },
          },
          symbol: 'circle',
          symbolSize: function (val: Array<any>) {
            return 5 + val[2] * 5 //圆环大小
          },
          itemStyle: {
            normal: {
              show: false,
              color: '#f8f9f5',
            },
          },
          data: item[1].map(function (dataItem: any) {
            return {
              name: dataItem[0].name,
              value: chinaGeoCoordMap[dataItem[0].name].concat([dataItem[0].value]),
            }
          }),
        },
        //被攻击点
        {
          type: 'effectScatter',
          coordinateSystem: 'geo',
          zlevel: 2,
          rippleEffect: {
            //涟漪相关
            period: 2,
            brushType: 'stroke',
            scale: 5,
          },
          label: {
            normal: {
              show: true,
              position: 'right',
              // offset:[5, 0],
              color: '#0f0',
              formatter: '{b}',
              textStyle: {
                color: '#fff',
                fontSize: 12,
              },
            },
            emphasis: {
              show: true,
              color: '#f60',
            },
          },
          itemStyle: {
            normal: {
              color: '#f00',
            },
          },
          symbol: 'circle',
          symbolSize: 10, //圆圈大小
          data: [
            {
              name: item[0],
              value: chinaGeoCoordMap[item[0]].concat([10]),
            },
          ],
        },
      )
    })
    
    /****************************************************************/
    function drawChina() {
      var myChart = echarts.init(chinaMap.value)
      echarts.registerMap('china', chinaJson) //注册可用的地图
      var option = {
        tooltip: {
          trigger: 'item',
          backgroundColor: 'rgba(166, 200, 76, 0.82)',
          borderColor: '#FFFFCC',
          showDelay: 0,
          hideDelay: 0,
          enterable: true,
          transitionDuration: 0,
          extraCssText: 'z-index:100',
          formatter: function (params, ticket, callback) {
            //根据业务自己拓展要显示的内容
            var res = ''
            var name = params.name
            var value = params.value[params.seriesIndex + 1]
            res = "<span style='color:#fff;'>" + name + '</span><br/>数据:' + value
            return res
          },
        },
        geo: {
          show: true,
          center: [105.194115019531, 35.582111640625],
          map: 'china',
          roam: true, //是否允许缩放,拖拽
          zoom: 1, //初始化大小
          //缩放大小限制
          scaleLimit: {
            min: 0.1, //最小
            max: 12, //最大
          },
          //设置中心点
          //center: [95.97, 29.71],
          //省份地图添加背景
          //regions: regions,
          itemStyle: {
            normal: {
              areaColor: '#3352c7',
              color: 'red',
              borderColor: '#5e84fd',
              borderWidth: 2,
            },
          },
          label: {
            color: 'rgba(255,255,255,0.5)',
            show: false,
          },
          //高亮状态
          emphasis: {
            itemStyle: {
              areaColor: '#ffc601',
            },
            label: {
              show: true,
              color: '#fff',
            },
          },
          z: 10,
        },
        //配置属性
        series: series,
      }
      myChart.setOption(option)
    }
    </script>
    复制代码

     

  • 相关阅读:
    sed编辑器
    unity 创建项目报错feature has expired (H0041),sentinel key not found (H0007)
    浅谈python后端面试(附一些经典项目源码)
    电脑屏幕变色了怎么调回来,电脑屏幕颜色怎么改
    群狼调研(长沙口味测试)如何开展产品口味测试
    在裸机上输出Hello,world! [rCore-lab1]
    在pytorch中使用tensorboard
    流式DMA映射实践3:dmaengine与memcpy
    Learn Prompt-ChatGPT 精选案例:学习助理
    模型轻量化、模型减面、模型压缩、模型优化合集
  • 原文地址:https://www.cnblogs.com/web-learn/p/16107080.html