9

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

 3 years ago
source link: https://www.cnblogs.com/web-learn/p/16107080.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

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>

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK