3DMap大屏那些事儿

前言

做了一版基于高德地图的3D效果的大屏,由于高德API地图主题就那么几种,无法按需调整色调以及更换背景图(理论上应该是可行的,通过图层等相关控制),继续换方案,换成使用 ECharts 相关技术栈实现3D地图效果

本文主要整理面向AI和搜索引擎开发过程遇到的一些情况和处理方案,文章中主要提供关键代码和思路介绍,完整代码运行在文末有 GitHub 源码地址

方案实现

引入关键包

3D效果实现主要是加了 echarts-gl 这个包,其他的配置和普通图表类似

js 复制代码
import * as echarts from "echarts";
import "echarts-gl"; //3D地图插件

引入GeoJSON 文件

这个文件是地图轮廓坐标点,例如我这里用的是北京市朝阳区的街道地图数据

js 复制代码
import geoJson from "./json/chaoyang_street.json"; //该文件路径改成自己项目中的文件路径即可

提示

高德和一些地图平台提供的一般只到区,例如北京市朝阳区,街道以及更深层的数据需要付费购买,可以通过购买高德的服务,调用接口获得街道数据,或者通过第三方平台购买相关数据

如果只是做一小块区域的效果,想获取相关坐标点,可以访问 geojson.io ,这个里面可以创建

验证数据

关于购买的 GeoJSON 数据或者通过别的格式转换过来的数据,在 geojson.io 里面验证数据是否正常

提示

如果数据格式不正确,会导致渲染异常或失败

构建地图

创建html元素

html 复制代码
<div class="map" id="mapEchart" style="width:100%;height:calc(100vh - 100px) ;"></div>

地图初始化

使用echarts.registerMap注册地图,这是地图效果的关键

js 复制代码
 var myChart = echarts.init(document.getElementById("mapEchart"));
  // 重点:不要遗漏这句代码!!
  echarts.registerMap("chaoyang", geoJson);

其他配置在 option 中进行即可,和 echarts 图表配置几乎一样

3D地图配置

3D地图的配置在 option 中添加 geo3D 配置,在 viewControl 中控制地图的角度,旋转 等动画效果,emphasis 中配置元素块移入的效果,完整配置如下

js 复制代码
    //3D地图配置项
    geo3D: {
      map: "chaoyang",
      roam: true,
      itemStyle: {
        color: "#007aff",
        opacity: 0.8,
        borderWidth: 0.4,
        borderColor: "#000",
        // areaColor: '#fff'
      },
      viewControl: {
        // autoRotate: true,
        autoRotate: false, // 关闭自动旋转
        autoRotateAfterStill: 3,
        distance: 190,// 增加距离值来缩小视图 (原值: 120)
        minAlpha: 5, // 上下旋转的最小 alpha 值。即视角能旋转到达最上面的角度。[ default: 5 ]
        maxAlpha: 90, // 上下旋转的最大 alpha 值。即视角能旋转到达最下面的角度。[ default: 90 ]
        minBeta: -360, // 左右旋转的最小 beta 值。即视角能旋转到达最左的角度。[ default: -80 ]
        maxBeta: 360, // 左右旋转的最大 beta 值。即视角能旋转到达最右的角度。[ default: 80 ]
        animation: true, // 是否开启动画。[ default: true ]
        animationDurationUpdate: 1000, // 过渡动画的时长。[ default: 1000 ]
        animationEasingUpdate: "cubicInOut", // 过渡动画的缓动效果。[ default: cubicInOut ]
        // alpha: 45, // 调整上下角度,让地图更往上一点 (新增)
        // beta: 10,   // 左右角度 (新增)
      },


      emphasis: {
        disabled: true, //是否可以被选中
        label: {
          //移入时的高亮文本
          show: true,
          color: "#333", //显示字体颜色变淡
          // fontSize: 18, //显示字体变大
          formatter: function (params) {
            // 可以返回任意自定义内容
            // return params.name;  // 显示区域名称
            // 或者
            return `${params.name}`;  // 自定义格式
          }
        },
        itemStyle: {
          color: "#ff7aff", //显示移入的区块变粉色
        },
      },
      label: {
        show: false,
        position: "top",
        color: "#111", //地图初始化区域字体颜色
        fontSize: 14,
        lineHeight: 16,
      },
      shading: "lambert",
      light: {
        //光照阴影
        main: {
          // color: "#fff", //光照颜色
          intensity: 1, //光照强度
          //shadowQuality: 'high', //阴影亮度
          shadow: true, //是否显示阴影
          shadowQuality: "medium", //阴影质量 ultra //阴影亮度
          alpha: 55,
          beta: 10,
        },
        ambient: {
          intensity: 0.7,
        },
      },
    },

注意!

绑定 map 参数为 echarts.registerMap("chaoyang", geoJson); 中注册的地图

绑定热力图数据块

在具体的业务中,移入街道需要显示对应的数据,这里使用3D柱状图效果显示数值,数据绑定在 series 中,注意 type 类型为 bar3D

js 复制代码
    series: [
      //3D柱状图配置项
      {
        name: "",
        type: "bar3D",
        coordinateSystem: "geo3D",
        barSize: 2,
        shading: "lambert",
        opacity: 0.1,
        bevelSize: 0.2,
        label: {
          show: false,
          formatter: "{a}",
        },
        data: [
          {
            name: '和平街街道', value: [116.408795, 39.971735, 100],
          }
        ]

      },
    ],

设置热力图的数据区间色块效果,添加 visualMap 设置

js 复制代码
    //热力图配置项
    visualMap: [
      {
        type: "continuous",
        text: ["高", "低"],
        show: false, // 隐藏视觉映射组件,但仍然应用其配置
        calculable: true,
        max: 250,
        inRange: {
          color: ["#87aa66", "#eba438", "#d94d4c"],
        },
      },
    ],

例如,这里添加了一个 和平街街道 的数据,注意 value 中的值,前两个为经纬度坐标,第三个为具体的数据,此时,地图效果就出来了,鼠标移入对应的柱子显示对应的街道数据

初版效果预览

此时3D效果有了,鼠标移入对应区域会变色,并且能显示对应的数据,但是在旋转时会有明显的渲染异常的效果,阴影闪来闪去的,需要优化优化

优化参数,提升流畅度

在初始化 echarts 时添加配置

js 复制代码
var myChart = echarts.init(document.getElementById("mapEchart"), null, { 
    devicePixelRatio: window.devicePixelRatio * 0.8, // 降低渲染精度 
    useDirtyRect: true, // 使用脏矩形渲染优化 
});

优化光照设置

调整光照参数以减少渲染复杂度

js 复制代码
light: {
  main: {
    intensity: 0.8, // 降低光照强度
    shadow: false,  // 关闭阴影以提高性能
    alpha: 45,
    beta: 10,
  },
  ambient: {
    intensity: 0.5, // 调整环境光
  },
},

调整 viewControl 设置

优化控制参数,减少渲染压力

js 复制代码
viewControl: {
  animationDurationUpdate: 500, // 减少动画时长
  animationEasingUpdate: "linear", // 使用线性动画
  damping: 0.8, // 阻尼系数
  rotateSensitivity: 1, // 旋转灵敏度
  zoomSensitivity: 1,   // 缩放灵敏度
  panSensitivity: 1,    // 平移灵敏度
},

注意!!!

上面的参数优化,我本地测试的这个例子里,在解决鼠标移入或鼠标控制地图旋转时颜色渲染闪烁问题上并不明显,而且调整光影等参数时还会出现把原本设置的地图的颜色效果给影响了,效果变暗,整体感觉更差了 尴尬+1

优化GeoJSON

3D效果渲染,还有一种情况是数据量太大了,导致的效果每次重新渲染时内容太多出现闪烁问题,先看原始数据坐标点

例如某个街道的坐标点行数 1000+, 整个 GeoJSON 文件 2174KB,明显也太大了, 可以在https://mapshaper.org/ 中的 simplfy 简化格式

根据需要简化格式,例如这里设置简化到了 10.8%,边界的轮廓有细微的变化,相对原始数据效果颗粒度没那么明显了

这是原数据的效果

在简化到 10.8% 后保持基本的轮廓,GeoJSON 文件缩小到了 619KB,相对原来的 2174KB 的文件体积缩小了两倍多,chaoyang_street.json 是简化后的数据文件, chaoyang_street_origin.json 是原始数据文件

这样缩小后,3D地图的效果明显流畅了很多,鼠标移入和通过鼠标旋转地图不同的街道区域的多边形的颜色也不会那么卡了

优化后效果

代码仓库地址

github.com/gywgithub/F...

3D地图代码地址

github.com/gywgithub/F...

如果本地运行测试效果,将 Front-end-function-examples 仓库克隆到本地,然后进入 my-project-vue3 项目中,在根目录运行 vue3 项目即可

技术栈版本

  • "echarts": "5.5.0",
  • "echarts-gl": "^2.0.9",
  • "vue": "^3.4.29",

写在最后

关于ECharts 3D Map 可能也有其他的实现方案, 也有其他可优化的空间,欢迎大家评论区讨论交流,一起学习共同进步

如果喜欢本文章或感觉文章有用,动动你那发财的小手点赞、收藏、关注再走呗 ^_^

微信公众号:草帽Lufei

相关推荐
龙在天几秒前
你只会console.log就Out了
前端
用户681722457211 分钟前
h5实现点击电话进入拨打电话功能
前端
菠萝+冰1 小时前
在 React 中,父子组件之间的通信(传参和传方法)
前端·javascript·react.js
庚云1 小时前
一套代码如何同时适配移动端和pc端
前端
Jinuss1 小时前
Vue3源码reactivity响应式篇Reflect和Proxy详解
前端·vue3
海天胜景1 小时前
vue3 el-select 默认选中第一个
前端·javascript·vue.js
小小怪下士_---_1 小时前
uniapp开发微信小程序自定义导航栏
前端·vue.js·微信小程序·小程序·uni-app
前端W1 小时前
腾讯地图组件使用说明文档
前端
页面魔术1 小时前
无虚拟dom怎么又流行起来了?
前端·javascript·vue.js
胡gh1 小时前
如何聊懒加载,只说个懒可不行
前端·react.js·面试