手把手教 Vue3.2+Vite+Echarts 5 绘制3D线条效果中国地图

这篇具有很好参考价值的文章主要介绍了手把手教 Vue3.2+Vite+Echarts 5 绘制3D线条效果中国地图。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


echarts 3d中国地图,vue,echarts,3d,javascript,vue.js,前端

简介

本篇文章介绍 Vue3.2+Vite 项目内使用 Echarts 5 绘制中国地图,标记分布点!之前没有接触过 Echarts 的,可以先去官方示例看看,里面图形特别齐全。但是官方文档看着费劲的,太多了根本记不住,所以自己做个总结,下次就可以直接使用了,不用做重复无用功。

安装插件

1、下载并引入 echarts

Echarts 已更新到了 5.0以上 版本,安装完记得检查下自己的版本是否是 5.0以上版本 。
安装完成之后,在 package.json 中检查是否安装成功?

// `安装`
npm install echarts --save

echarts 3d中国地图,vue,echarts,3d,javascript,vue.js,前端

2、下载地图的 json 数据

阿里云下载中国以及各个省份地图数据,免费的文件下载地址:
传送门【下载地址】

引入需要绘制的地图数据 json 或 js 文件,本文使用的是 json 格式

// 地图的 json 数据
import chinaJson from '../utils/china.json'

3、全局引入或局部引入(我这里选择单页面局部引入)

1、全局引入在man.js中引入挂载;
2、单页面引入方式:

<script setup>
  import * as echarts from 'echarts'
  import chinaJson from '../utils/china.json'
 </script>

3、准备容器

// 
<div ref="chinaMap" class="map"></div>

4、实例化 echarts 对象

<script setup>
  import * as echarts from 'echarts'
  import chinaJson from '../utils/china.json' // 地图的 json 数据
	
   // 初始化
  const chinaMap = ref()
  var myChart = echarts.init(chinaMap.value)
  echarts.registerMap('china', chinaJson) //注册可用的地图
 </script>

5、指定配置项和数据

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

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

1、开始绘制
const drawChina = () => {
    var myChart = echarts.init(chinaMap.value)
    echarts.registerMap('china', chinaJson) //注册可用的地图
    var option = {
      tooltip: {
        trigger: 'item',
        backgroundColor: 'rgba(252, 252, 252, 0.82)',
        borderColor: '#fff',
        showDelay: 0,
        hideDelay: 0,
        enterable: true,
        transitionDuration: 0,
        extraCssText: 'z-index:100',
        formatter: (params, ticket, callback) => {
          //根据业务自己拓展要显示的内容
          // console.log(params,'params',)
          var res = ''
          var initss = 0
          var newArry = ''
          var name = params.name
          // var value = params.value[params.seriesIndex + 1]
          if (params.data.ints > 0) {
            initss = params.data.ints
          }
          if (params.data.tit?.length > 0) {
            newArry = Array.from(params.data.tit,(item)=> item.title)
          }
          res = "<div style='max-width:500px;white-space:pre-wrap;'><span>" + name + '</span>旅游:'+ "<div style='color: red;'>" + newArry + "</div></div>"
          return res
        },
      },
      geo: {
        show: true,
        center: [105.194115019531, 35.582111640625],
        map: 'china',
        roam: drawChinaObj.roam, //是否允许缩放,拖拽
        zoom: drawChinaObj.zoom, //初始化大小
        //缩放大小限制
        scaleLimit: {
          min: 0.1, //最小
          max: 12, //最大
        },
        //设置中心点
        //center: [95.97, 29.71],
        //省份地图添加背景
        //regions: regions,
        itemStyle: {
          // normal: {
          areaColor: '#3352c7',
          color: '#e91e63',
          borderColor: '#5e84fd',
          borderWidth: 2,
          // },
        },
        label: {
          color: 'rgba(255,255,255,0.5)',
          show: false,
        },
        //高亮状态
        emphasis: {
          label: {
            show: true,
            color: '#fff',
          },
          itemStyle: {
            areaColor: '#e91e63',
          },
        },
        z: 10,
      },
      //配置属性
      series: series,
    }
    myChart.setOption(option)
  }

2、线条动画效果关键代码处理:

var series = []
    ;[['上海', chinaDatas]].forEach((item, i) => {
      series.push(
        //设置指向箭头信息
        {
          type: 'lines',
          zlevel: 2,
          effect: {
            show: true,
            period: 4, //箭头指向速度,值越小速度越快
            trailLength: 0.02, //特效尾迹长度[0,1]值越大,尾迹越长重
            symbol: 'arrow', //箭头图标
            symbolSize: 8, //图标大小
          },
          coords:[[1,2],[2,3]],
          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, //波纹圆环最大限制,值越大波纹越大
          },
          itemStyle: {
            // normal: {
            show: false,
            color: '#f8f9f5',
            // },
          },
          label: {
            // normal: {
            show: true,
            position: 'right', //显示位置
            offset: [5, 0], //偏移设置
            formatter: function (params) {
              //圆环显示文字
              return params.data.name
            },
            fontSize: 13,
            // },
            emphasis: {
              show: true,
            },
          },
          symbol: 'circle',
          symbolSize: (val) => {
            return 5 + val[2] * 5 //圆环大小
          },

          data: item[1].map((dataItem) => {
            return {
              name: dataItem[0].name,
              tit: dataItem[0].obj,
              ints: dataItem[0].ints,
              value: chinaGeoCoordMap[dataItem[0].name].concat([dataItem[0].value]),
            }
          }),
        },
        //被攻击点
        {
          type: 'effectScatter',
          coordinateSystem: 'geo',
          zlevel: 2,
          rippleEffect: {
            //涟漪相关
            period: 2,
            brushType: 'stroke',
            scale: 5,
          },
          itemStyle: {
            color: '#f00',
          },
          label: {
            show: true,
            position: 'right',
            // offset:[5, 0],
            color: '#0f0',
            formatter: '{b}',
            textStyle: {
              color: '#fff',
              fontSize: 12,
            },
            emphasis: {
              show: true,
              color: '#f60',
            },
          },
          symbol: 'circle',
          symbolSize: 10, //圆圈大小
          data: [
            {
              name: item[0],
              value: chinaGeoCoordMap[item[0]].concat([10]),
            },
          ],
        },
      )
    })

项目实践

最后分享完美案例

<template>
  <div class="page">
    <div class="h1">管理后台大屏可视化界面</div>
    <!-- 封装组件全局挂载 -->
    <div class="time">
      <mm-time />
    </div>
    <div class="ul">
      <span @click="onClickOpen(1)">还原</span>
      <span @click="onClickOpen(2)" :class="{'spanBg': !drawChinaObj.roam}">固定</span>
      <span @click="onClickOpen(3)">缩放+</span>
      <span @click="onClickOpen(4)">缩放-</span>
      <span @click="onClickOpen(5)">刷新</span>
    </div>
    <!-- 组件小提示 -->
    <div class="tip">
      <TextSoll />
    </div>
    <div ref="chinaMap" class="map"></div>
  </div>
</template>

<script setup>
  import * as echarts from 'echarts'
  import chinaJson from '../utils/china.json'
  import TextSoll from '@/components/textSoll.vue'
  const { proxy } = getCurrentInstance()

  onMounted(() => {
    drawChina()
  })

  // 事件
  const onClickOpen = (e) => {
    if (e == 1) {
      drawChinaObj.roam = true
      drawChinaObj.zoom = 1.5
    } else if (e == 2) {
      drawChinaObj.roam = false
    } else if (e === 3) {
      drawChinaObj.zoom = drawChinaObj.zoom + 0.2
    } else if (e === 4) {
      drawChinaObj.zoom = drawChinaObj.zoom - 0.2
    } else {
      drawChina()
    }
    drawChina()
  }

  // 初始化
  const chinaMap = ref()
  const drawChinaObj = reactive({
    hint: proxy.$utlis.handleTips(),
    roam: false,
    zoom: 1.5,
  })
  /**
   * 设置投射点
   * 中国地理坐标图
   */
  const chinaGeoCoordMap = {
    上海: [121.46503408447266, 31.221068849156694],
    湖南省张家界: [110.54218025390624, 29.122992832430285],
    湖南省凤凰古城: [109.10110225, 27.4452938],
    浙江省杭州西湖: [120.1941180322266, 30.23469703027832],
    重庆市: [109.40093,31.018551],
    广西省北海涠洲岛: [109.23477202734375,20.857876355435824],
    哈尔滨市: [127.16687354565428,45.45942366122554],
  }
  const chinaDatas = [
    [
      {
        name: '湖南省张家界',
        value: 1,
        ints: 10,
        obj: [
          {title: '张家界(1次)'},
        ]
      },
    ],
    [
      {
        name: '湖南省凤凰古城',
        value: 1,
        ints: 10,
        obj: [
          {title: '凤凰古城(1次)'},
        ]
      },
    ],
    [
      {
        name: '浙江省杭州西湖',
        value: 1,
        ints: 10,
        obj: [
          {title: '杭州西湖(1次)'}
        ]
      },
    ],
    [
      {
        name: '重庆市',
        value: 1,
        ints: 10,
        obj: [
          {title: '巴南区花园(1次)'},
          {title: '奉节县白帝城(1次)'},
        ]
      },
    ],
    [
      {
        name: '广西省北海涠洲岛',
        value: 1,
        ints: 10,
        obj: [
          {title: '北海涠洲岛(1次)'}
        ]
      },
    ],
    [
      {
        name: '哈尔滨市',
        value: 1,
        ints: 10,
        obj: [
          {title: '哈尔滨市'}
        ]
      }
    ]

  ]
  const scatterPos = [121.46503408447266, 31.221068849156694]
  // 1
  const convertData = (data) => {
    var res = []
    for (var i = 0; i < data.length; i++) {
      var dataItem = data[i]
      var fromCoord = chinaGeoCoordMap[dataItem[0].name]
      console.log(dataItem,'fromCoord')
      var toCoord = scatterPos
      if (fromCoord && toCoord) {
        res.push([
          {
            tit: dataItem[0].obj,
            coord: fromCoord,
            value: dataItem[0].value,
          },
          {
            coord: toCoord,
          },
        ])
      }
    }
    console.log('res', res)
    return res
  }
  // 2
  var series = []
    ;[['上海', chinaDatas]].forEach((item, i) => {
      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, //图标大小
          },
          coords:[[1,2],[2,3]],
          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, //波纹圆环最大限制,值越大波纹越大
          },
          itemStyle: {
            // normal: {
            show: false,
            color: '#f8f9f5',
            // },
          },
          label: {
            // normal: {
            show: true,
            position: 'right', //显示位置
            offset: [5, 0], //偏移设置
            formatter: function (params) {
              //圆环显示文字
              return params.data.name
            },
            fontSize: 13,
            // },
            emphasis: {
              show: true,
            },
          },
          symbol: 'circle',
          symbolSize: (val) => {
            return 5 + val[2] * 5 //圆环大小
          },

          data: item[1].map((dataItem) => {
            return {
              name: dataItem[0].name,
              tit: dataItem[0].obj,
              ints: dataItem[0].ints,
              value: chinaGeoCoordMap[dataItem[0].name].concat([dataItem[0].value]),
            }
          }),
        },
        //被攻击点
        {
          type: 'effectScatter',
          coordinateSystem: 'geo',
          zlevel: 2,
          rippleEffect: {
            //涟漪相关
            period: 2,
            brushType: 'stroke',
            scale: 5,
          },
          itemStyle: {
            color: '#f00',
          },
          label: {
            show: true,
            position: 'right',
            // offset:[5, 0],
            color: '#0f0',
            formatter: '{b}',
            textStyle: {
              color: '#fff',
              fontSize: 12,
            },
            emphasis: {
              show: true,
              color: '#f60',
            },
          },
          symbol: 'circle',
          symbolSize: 10, //圆圈大小
          data: [
            {
              name: item[0],
              value: chinaGeoCoordMap[item[0]].concat([10]),
            },
          ],
        },
      )
    })
  // 3
  const drawChina = () => {
    var myChart = echarts.init(chinaMap.value)
    echarts.registerMap('china', chinaJson) //注册可用的地图
    var option = {
      tooltip: {
        trigger: 'item',
        backgroundColor: 'rgba(252, 252, 252, 0.82)',
        borderColor: '#fff',
        showDelay: 0,
        hideDelay: 0,
        enterable: true,
        transitionDuration: 0,
        extraCssText: 'z-index:100',
        formatter: (params, ticket, callback) => {
          //根据业务自己拓展要显示的内容
          // console.log(params,'params',)
          var res = ''
          var initss = 0
          var newArry = ''
          var name = params.name
          // var value = params.value[params.seriesIndex + 1]
          if (params.data.ints > 0) {
            initss = params.data.ints
          }
          if (params.data.tit?.length > 0) {
            newArry = Array.from(params.data.tit,(item)=> item.title)
          }
          res = "<div style='max-width:500px;white-space:pre-wrap;'><span>" + name + '</span>旅游:'+ "<div style='color: red;'>" + newArry + "</div></div>"
          return res
        },
      },
      geo: {
        show: true,
        center: [105.194115019531, 35.582111640625],
        map: 'china',
        roam: drawChinaObj.roam, //是否允许缩放,拖拽
        zoom: drawChinaObj.zoom, //初始化大小
        //缩放大小限制
        scaleLimit: {
          min: 0.1, //最小
          max: 12, //最大
        },
        //设置中心点
        //center: [95.97, 29.71],
        //省份地图添加背景
        //regions: regions,
        itemStyle: {
          // normal: {
          areaColor: '#3352c7',
          color: '#e91e63',
          borderColor: '#5e84fd',
          borderWidth: 2,
          // },
        },
        label: {
          color: 'rgba(255,255,255,0.5)',
          show: false,
        },
        //高亮状态
        emphasis: {
          label: {
            show: true,
            color: '#fff',
          },
          itemStyle: {
            areaColor: '#e91e63',
          },
        },
        z: 10,
      },
      //配置属性
      series: series,
    }
    myChart.setOption(option)
  }

</script>

<style lang="less" scoped>
.page {
  width: 100%;
  height: 100%;
  background-image: url(xxxxxxxxxxx);
  background-position: 0% 0%;
  background-size: 100% 100%;
  background-repeat: initial;
  background-attachment: initial;
  background-origin: initial;
  background-clip: initial;
  position: relative;

  .h1 {
    position: absolute;
    width: 100%;
    top: 4%;
    text-align: center;
    // padding: 27px 0;
    font-size: 26px;
    font-weight: bold;
    color: #fff;
    letter-spacing: 4px;
  }
  .time {
    position: absolute;
    width: 300px;
    top: 6%;
    left: 2%;
    color: #fff;
    text-align: center;
    z-index: 100;
  }
  .ul {
    position: absolute;
    width: 100%;
    top: 12%;
    z-index: 9;

    font-size: 12px;
    color: #fff;
    text-align: center;
    margin-top: 10px;
    span {
      color: #03A9F4;
      padding: 4px 12px;
      border-radius: 4px;
      border: 2px solid #03A9F4;
      margin-left: 10px;
      cursor: pointer;
      &:first-child {
        margin-left: 0px;
      }
      &:active {
        color: #fff;
        background-color: rgba(137, 192, 243, 0.82)
      }
    }
    .spanBg {
      color: #fff;
      background-color: rgba(137, 192, 243, 0.82)
    }
  }
  .tip {
    position: absolute;
    width: 360px;
    top: 6%;
    right: 2%;
    color: #b9b5b5;
    float: right;
  }
  .map {
    width: 100%;
    margin: auto;
    height: calc(100vh);
    position: relative;

    // width: 100%;
    // height: calc(100vh - 90px);
    // background: rgba(6, 58, 214, 0.1);
    transform: rotate3d(1, 0, 0, 35deg);
  }
}
</style>




总结:

前端路上 | 所知甚少,唯善学。
各位小伙伴有什么疑问,欢迎留言探讨。

— 关注我:前端路上不迷路 —文章来源地址https://www.toymoban.com/news/detail-762203.html




到了这里,关于手把手教 Vue3.2+Vite+Echarts 5 绘制3D线条效果中国地图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 手把手教你用 Docker 部署 Vue3 项目

    手把手教你用 Docker 部署 Vue3 项目

    用 docker 可以帮我们快速部署前端项目,本文介绍了如何用 docker 快速部署 vue3 项目。请准备好一台云服务器并安装好 docker,然后开始阅读本教程。 执行 npm run build 打包后项目目录中会多出一个 dist 文件夹 利用 docker 拉取 nginx 镜像 在服务器中创建工作目录,这里我放在 /ho

    2024年02月05日
    浏览(21)
  • vue系列(三)——手把手教你搭建一个vue3管理后台基础模板

    vue系列(三)——手把手教你搭建一个vue3管理后台基础模板

    目录 一、前言: 二、网站页面分析 三、开发步骤 (一)、安装element (二)、安装使用svg插件 (三)、编写主界面框架代码  (四)、编写菜单栏  (五)、新建页面及路由 (六)、定制页面标签栏 第一步: 第二步: (七)、修改封装菜单栏 (八)、添加面包屑 四、结

    2023年04月24日
    浏览(17)
  • 手把手教你绘制小程序海报

    手把手教你绘制小程序海报

    海报分享功能在许多应用中应该是很常见的,因为它作为一种常用的应用推广和拉新的方式。 接下来看个实际的案例,如下: 把任务拆解下: 如何绘制海报 如何把绘制后的海报保存到相册 用 canvas 来绘制海报。 这里需要了解基本的 canvas api ,不熟悉可以先去了解下相关

    2024年02月04日
    浏览(14)
  • 手把手带你开发Cesium三维场景【3D智慧城市警情预警】

    手把手带你开发Cesium三维场景【3D智慧城市警情预警】

    📢 鸿蒙专栏:想学鸿蒙的,冲 📢 C语言专栏:想学C语言的,冲 📢 VUE专栏:想学VUE的,冲这里 📢 CSS专栏:想学CSS的,冲这里 📢 Krpano专栏:想学VUE的,冲这里 🔔 上述专栏,都在不定期持续更新中!!!!!!!!!!!!! ​​ 警情模拟示例 本文主要用于构建Ce

    2024年02月03日
    浏览(18)
  • 手把手教你在windows下源码编译Open3D

    手把手教你在windows下源码编译Open3D

    首先不建议windows下源码编译,需要用C++的可以直接下载官网编译好的版本。熟悉vcpkg的,可以把open3d加到vcpkg使用,参考该博客。 cmake =3.20 python =3.6.0 visual studio =2017 Github下载open3d源码 打开源码,新建build文件夹 填写你的VS版本,例vs2022(17),open3d_install_directory使用当前路径

    2024年02月05日
    浏览(17)
  • vue项目打包部署-手把手教程

    vue项目打包部署-手把手教程

    1.购买服务器 可选阿里云/腾讯云/华为云 等等… 购买时选择镜像,我们这里以CentOS为例 2.配置服务器 2.1 安装FinalShell ​ 需要本地使用一些软件来操作服务器,例如:FinalShell / Xshell … ​ 我这里使用的是FinalShell,安装好以后,打开软件与建立链接,就可以用命令行来操作服务器了 最

    2024年02月22日
    浏览(16)
  • [手把手系列之]Docker 部署 vue 项目

    [手把手系列之]Docker 部署 vue 项目

    Docker 作为轻量级虚拟化技术,拥有持续集成、版本控制、可移植性、隔离性和安全性等优势。本文使用Docker来部署一个vue的前端应用,并尽可能详尽的介绍了实现思路和具体步骤,以方便有类似需要的同学参考。 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应

    2024年03月24日
    浏览(13)
  • Docker容器部署前端Vue服务——手把手教学

    Docker容器部署前端Vue服务——手把手教学

    需要工具: Xftp Xshell   首先对前端项目进行打包:npm run build   打包完成 ​ 在项目中生成dist文件: 通过Xshell在/home目录下创建项目文件夹 通过Xftp将打包的dist文件上传到服务器的项目文件夹下; 利用Xshell在拉取nginx镜像 在项目文件夹下编写nginx config配置文件 default.conf内容

    2024年02月07日
    浏览(12)
  • 手把手教你在Windows下搭建Vue开发环境

    手把手教你在Windows下搭建Vue开发环境

    最近有小伙伴不会Vue环境的部署,小孟亲自测试了下,大家有需要的可以按照下面的学习。 如果想看视频的,也可以看视频的教程: https://www.bilibili.com/video/BV1if4y1X7BS/?spm_id_from=333.788.recommend_more_video.-1vd_source=e64f225fc5daf048d2687502cb23bb3b 在Windows下搭建Vue开发环境: 官网https://n

    2024年02月08日
    浏览(16)
  • Vue Router的详细解读之手把手教学篇(一)

            Vue Router是Vue项目开发中,重要的一环,在页面模块的模块化,数据参数的传递,等方面具有重要的作用,Vue是单页面应用,通过路由控制页面所展示的内容,下面让我们一起学习一下关于Vue Route的基础用法,其中包含博主的整理总结。 用 Vue + Vue Router 创建单页应用

    2024年02月08日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包