三维可视化:使用 ECharts-GL 实现世界级、国家级、省市级 3D 地图

一. 前言

在数据可视化领域,二维地图早已司空见惯,它以直观的方式呈现数据关系,帮助我们理解复杂的信息。然而,在追求更优(高大上)用户体验的今天,传统的二维展示方式已经不满足客户的体验需求,同时平面图表也难以充分展现地理信息的丰富维度和空间关系。于是,三维数据可视化越来越受到广大用户的青睐。

ECharts-GL ,作为 ECharts 家族的一员,更是专为三维数据可视化而生,它不仅继承了 ECharts 的易用性和高性能,还引入了 WebGL 技术,为用户提供了一个强大且直观的工具,用于创建令人惊叹的 3D 地图和数据可视化作品。

本篇文章,你将学习到如何利用 ECharts-GL 构建沉浸式的 3D 地图体验。并学习如何配置和定制地图的部分细节,包括地形、光照、视角 以及纹理的三维表示。

通过本篇文章,你将学习到以下内容:

  • 基础 3D 地图的实现逻辑
  • 丰富 3D 地图的配置项
  • 世界级、国家级、省市区级别 3D 地图展示

本篇文章既是 3D 地图的扫盲篇章,也是开启你从二维地图迈向三维世界的开端,让你从零到一,循序渐进的完整实现各种 3D 地图的渲染!

预览效果图如下图所示:

二. 准备 geoJson 数据

首先,我们需要准备多层级的地图数据,比如世界、国家、省份、城市等各级别的地理数据,以及每个区域对应的数据指标,这些数据通常是以 JSON 格式提供的地理信息数据。同时,确保数据格式符合 ECharts 的要求,可以参考官方文档了解各种地图类型的数据格式。

我们可以在一些其他网站获取最新的 geoJson,比如:我是通过阿里云 DataV 数据可视化平台下载最新的 json 数据文件,以保证目前所有市区的数据都是最新的。

如下图所示,选择数据版本后,点击页面上的下载按钮后即可以下载 json 文件:

也可以使用在线的 JSON API 接口获取数据,API 地址:geo.datav.aliyun.com/areas_v3/bo...

注意:如遇 403 Forbidden 错误,请参考文章巧用 meta 标签,设置 referrer 解决 403 Forbidden 问题

因为后面我会逐步实现世界级、国家级、城市级的 3D 地图,所以在这里我准备了这几个 json 文件,可以通过在线 API 获取:

准备好以上地图数据,接下来我们继续进行,最终实现世界地图,中国地图,山东省地图,青岛市地图等 3D 地图展示。

三. 初步实现 3D 地图

以中国地图 - 3D 地图的实现为例,接下来我们一步一步进行从零到一逐步丰富地图的显示

1. 加载 geoJson 数据

js 复制代码
const geoJson = "获取的的中国地图json";
const myChart = echarts.init(document.getElementById("main"));
// 注册地图名字(china)和数据(geoJson)
echarts.registerMap("china", geoJson);
// 图表配置项
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
    },
  ],
};
// 设置图表实例的配置项以及数据
myChart.setOption(option);

通过以上最基础的代码,就可以渲染出最基础的 3D 中国地图,如下图所示:

2. 设置地图的颜色

itemStyle 主要用来设置三维地图中三维图形的视觉属性,包括颜色,透明度,描边等。

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      // 地图的颜色
      itemStyle: {
        color: "#286ECA", // 地图板块的颜色
        opacity: 1, // 图形的不透明度 [ default: 1 ]
        borderWidth: 0.5, // (地图板块间的分隔线)图形描边的宽度。加上描边后可以更清晰的区分每个区域
        borderColor: "#286ECA", // 图形描边的颜色。[ default: #333 ]
      },
    },
  ],
};

3. 设置标签显示

label 主要用来配置地图上的城市名称是否显示标签,同时对标签的显示格式、显示样式进行配置

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      // 标签的相关设置
      label: {
        show: true, // (地图上的城市名称)是否显示标签
        distance: 5,
        formatter: function (params) {
          return params.name ? params.name : " ";
        },
        textStyle: {
          // 标签的字体样式
          color: "#fff", // 地图初始化区域字体颜色
          fontSize: 8, // 字体大小
        },
      },
    },
  ],
};

4. 设置鼠标 hover 高亮效果

emphasis 主要用来设置鼠标 hover 高亮时图形和标签的样式 (当鼠标放上去时 label 和 itemStyle 的样式)

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      // 鼠标 hover 高亮时图形和标签的样式
      emphasis: {
        label: {
          // label 高亮时的配置
          show: true,
          textStyle: {
            color: "#fff", // 高亮时标签颜色变为 白色
            fontSize: 15, // 高亮时标签字体 变大
          },
        },
        itemStyle: {
          // itemStyle 高亮时的配置
          color: "#66ffff", // 高亮时地图板块颜色改变
        },
      },
    },
  ],
};

5. 设置 tootip

tooltip 为提示框组件,它的设置属于 ECharts 的基础配置项,提示框组件可以设置在多种地方,主要作用为当鼠标鼠标悬浮到地图上时,提示框浮层的显示效果,详细配置参考文档:ECharts tooltip

js 复制代码
const option = {
  tooltip: {
    trigger: "item",
    position: "inside",
    formatter: "{b}",
    backgroundColor: "rgba(50, 50, 50, 0.7)",
    textStyle: {
      color: "#FFFFFF",
      textalign: "center",
      fontSize: "12px",
    },
  },
  series: [
    {
      type: "map3D",
      map: "china",
    },
  ],
};

四. 丰富 3D 地图的配置

1. 环境贴图

环境贴图 environment 主要支持 3 种配置方式,支持纯颜色值,渐变色,全景贴图的 url。默认为 'auto'

简单说:环境贴图可以看作是地图的底层背景。

  • 配置为全景贴图
    • environment: 'asset/environment.png'
  • 配置为纯黑色的背景
    • environment: '#000'
  • 配置为垂直渐变的背景
    • 通过 new echarts.graphic.LinearGradient 来配置

注意:在配置有 light.ambientCubemap.texture 的时候会使用该纹理作为环境贴图。否则不显示环境贴图。

在这里,我们使用垂直渐变的背景色来配置

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      // 环境贴图,支持純颜色值,渐变色,全景贴图的 url。默认为 'auto'
      environment: new echarts.graphic.LinearGradient(
        0,
        0,
        0,
        1,
        [
          {
            // 配置为垂直渐变的背景
            offset: 0,
            color: "#183890", // 天空颜色
          },
          {
            offset: 0.7,
            color: "#040829", // 地面颜色
          },
          {
            offset: 1,
            color: "#040829", // 地面颜色
          },
        ],
        false
      ),
    },
  ],
};

2. 设置地面

groundPlane 主要用来配置地面,可以让整个组件有个"摆放"的地方,从而使整个场景看起来更真实,更有模型感。

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      // 地面可以使整个场景看起来更真实,更有模型感。
      groundPlane: {
        show: true, // 是否显示地面
        color: "#aaa", // 地面颜色
      },
    },
  ],
};

3. 设置光照

light 主要用来配置关照,主要有:场景主光源、全局环境光等,合理的光照设置能够让整个场景的明暗变得更丰富,更有层次。

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      // 光照相关的设置
      light: {
        main: {
          // 场景主光源的设置,在 globe 组件中就是太阳光。
          color: "#3D94CE", // 主光源的颜色。
          intensity: 1.2, // 主光源的强度。
          shadow: false, // 主光源是否投射阴影。默认关闭。开启阴影可以给场景带来更真实和有层次的光照效果。会增加程序的运行开销。
          shadowQuality: "high", // 阴影的质量。可选'low', 'medium', 'high', 'ultra'
          alpha: 55, // 主光源绕 x 轴,即上下旋转的角度。配合 beta 控制光源的方向。
          beta: 10, // 主光源绕 y 轴,即左右旋转的角度。
        },
        ambient: {
          // 全局的环境光设置。
          color: "red", // 环境光的颜色。[ default: #fff ]
          intensity: 0.5, // 环境光的强度。[ default: 0.2 ]
        },
      },
    },
  ],
};

注意:在 shading 为 'color' 的时候无效。 光照的设置会影响到组件以及组件所在坐标系上的所有图表。

4. 设置视角控制

viewControl 的配置主要用于鼠标的旋转,缩放等视角控制。

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      viewControl: {
        projection: "perspective", // 投影方式
        autoRotate: true, // 是否开启视角绕物体的自动旋转查看
        autoRotateDirection: "cw", // 物体自传的方向。默认是 'cw',也可以取 'ccw'
        autoRotateSpeed: 10, // 物体自传的速度。角度 / 秒
        autoRotateAfterStill: 3, // 在鼠标静止操作后恢复自动旋转的时间间隔
        damping: 0, // 鼠标进行旋转,缩放等操作时的迟滞因子
        distance: 120, // 默认视角距离主体的距离
        alpha: 40, // 视角绕 x 轴,即上下旋转的角度
        beta: 0, // 视角绕 y 轴,即左右旋转的角度
        center: [0, 0, 0], // 视角中心点
        animation: true, // 是否开启动画
        animationDurationUpdate: 1000, // 过渡动画的时长
        animationEasingUpdate: "cubicInOut", // 过渡动画的缓动效果
      },
    },
  ],
};

以上代码设置了开启了自动旋转,如下图所示:

5. 设置纹理

在使用 echarts-gl 绘制 3D 地图时,为了增强地图的真实感,你可以设置纹理和光照效果。同时配合 lightpostEffect 使用可以让展示的画面效果和质感有质的提升。

下面我们具体来看一下简单示例:

js 复制代码
const option = {
  series: [
    {
      type: "map3D",
      map: "china",
      // 三维图形的着色效果
      shading: "realistic",
      // 真实感材质相关的配置项
      realisticMaterial: {
        detailTexture: "./img/texture.png", // 纹理图片
        textureTiling: 1,
      },
      // 后处理特效
      postEffect: {
        enable: true,
        SSAO: {
          enable: true,
          radius: 1,
          intensity: 1,
          quality: "high",
        },
        bloom: {
          enable: true,
          strength: 0.5,
          radius: 0,
          threshold: 0,
        },
        FXAA: {
          enable: true,
          alpha: 0.5,
        },
      },
      // 光照设置
      light: {
        main: {
          color: "#3D94CE",
          intensity: 1.2,
          shadow: false,
          shadowQuality: "high",
          alpha: 55,
          beta: 10,
        },
        ambient: {
          color: "#fff",
          intensity: 0.5,
        },
      },
    },
  ],
};

五. 显示不同级别的 3D 地图

通过上面的配置,地图的渲染效果已经逐渐有了效果还算不错的 3D 雏形,如果后续我们想要更好的视觉效果,可以参考官方文档配置项,一步步开发更加震撼的 3D 效果。

有了以上的配置项之后,接下来我们看一下如何进行渲染不同级别的地图,主要原理在于:根据不同的 geoJson 渲染不同的地图模型即可。

1. 世界级别

加载世界级的 geoJson 即可展示 3D 世界地图

2. 国家级别

加载国家级的 geoJson 即可展示 3D 国家版地图,例如:中国地图

3. 省份级别

加载省份级的 geoJson 即可展示 3D 省份地图,例如:山东省地图

4. 市区级别

加载市区级的 geoJson 即可展示 3D 市区地图,例如:青岛市地图

省级和城市级地图可能需要额外的处理,例如缩放和定位,以确保地图在 3D 视图中正确显示。此外,由于 echarts-gl 的设计,一些地图数据可能需要额外的调整才能在 3D 模式下正确渲染。

请注意:每个地图的 map 属性应该匹配你注册的地图数据的名称,如果你自己创建了地图数据并注册到 ECharts,那么 map 的值应该是你注册时所使用的名称。

最终预览效果图如下图所示:

六. 总结

通过本篇文章的介绍,相信我们大家都掌握了如何使用 ECharts 和 ECharts-GL 来构建世界级、国家级以及省市级的 3D 地图,更重要的是,本篇文章也是开启你从二维地图迈向三维世界的开端,让你从零到一,循序渐进的完整实现各种 3D 地图的渲染!

ECharts-GL 不仅提供了强大的 3D 渲染引擎,还支持高度定制化的地图样式和动态交互,使得数据可视化不再局限于图表和表格,因此在接下来的文章中,我将继续探索 ECharts-GL 在 3D 可视化大屏中的的应用,敬请关注!

七. 参考文档

八. 系列文章

关于 ECharts 的系列文章,感兴趣的朋友们可以查看以下文章进行了解:

本文正在参加金石计划征文活动,如果本文对您有帮助,麻烦点点收藏,点点赞!感谢

相关推荐
前端之虎陈随易44 分钟前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·vue.js·人工智能·typescript·node.js
一路向北he1 小时前
字节钢铁军团--“提供情境,而非控制”
java·开发语言·前端
kyriewen1 小时前
豆包和千问同时关了智能体,我用它们搭的 3 个自动化全废了——迁移方案整理
前端·javascript·ai编程
前端一小卒1 小时前
我用 TypeScript 从零手写了一个 Claude Code,然后发现它的核心只有 30 行
前端·agent
大圣编程3 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang3 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆4 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜4 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
尘中远4 小时前
【Qwt 7.0 系列】坐标轴与刻度系统 —— 刻度引擎、网格、图例与刻度朝内
qt·数据可视化·qcustomplot·qwt·工业软件·科学绘图
负责的蛋挞5 小时前
异步HttpModule的实现方式
java·服务器·前端