实现地图3d效果

1,074 阅读8分钟

Top1:使用 ECharts 的阴影和层叠实现3d效果

在本文中,我们将探讨如何使用 ECharts 库创建一个具有多层次视觉效果的三维中国地图。通过两种方法实现

准备工作

1. 引入 ECharts

确保你的项目中已安装了 ECharts。如果还没有安装,可以通过 npm 或 yarn 来安装:

npm install echarts
# 或者
yarn add echarts

2. 准备地图数据

ECharts 的地图数据通常需要单独引入。本例中使用了一个名为 echarts-3d-china.json 的文件,它包含了中国地图的地理信息。如果你没有地图数据的话可以通过:地图数据获取也可以访问我的仓库cv:仓库地址

创建三维地图组件

Vue 组件结构

首先,我们定义一个 Vue 3 组件的基本结构,包含一个用于绘制地图的 <div> 容器,并为其分配一个引用 chinaMapRef

<template>
  <div class="h-80 w-full flex flex-col">
    <div ref="chinaMapRef" class="flex-1 h-0"></div>
  </div>
</template>

初始化 ECharts 实例

<script setup> 部分,我们初始化 ECharts 实例,注册中国地图数据,并设置地图的配置选项。

<script setup>
import * as echarts from "echarts";
import china from "../echarts-3d-china.json";
import { ref, shallowRef, onMounted } from "vue";
import { useEchartsResizeAndDestory } from "../hooks/EchartsResizeAndDestoryHooks";

const chinaMapRef = ref(null);
const chinaInstance = shallowRef();

// ECharts 配置项
const option = {
  // ...此处省略配置项细节,具体配置见下文
};

// 注册地图数据
echarts.registerMap("china", china);

// 初始化图表
onMounted(() => {
  init();
});

const init = () => {
  const echartsContainer = chinaMapRef.value;
  if (!echartsContainer) return;

  chinaInstance.value = echarts.init(echartsContainer);
  chinaInstance.value.setOption(option);
};
</script>

ECharts 配置详解

配置项 option 是 ECharts 的核心,控制着地图的样式、交互等各个方面。以下是关键部分的配置说明:

提示框(tooltip)
  • show: true: 启用工具提示。
  • triggerOn: 'mousemove': 当鼠标移动时触发工具提示。
  • formatter: function(e) { return e.name; }: 自定义工具提示内容,仅显示地区名称。
地理坐标系(geo)
  • 四层地图:通过定义四个层次的 geo 配置,每个层次有不同的 z 值控制其堆叠顺序,以及不同的视觉效果(如颜色、阴影、边框宽度等),从而创建出立体感。
  • regions: 针对“南海诸岛”进行特殊处理,使其在上层显示,下层透明或不显示。
  • emphasisselect: 定义鼠标悬停或选中状态下的样式变化。
系列(series)
  • 只定义了一个地图系列,类型为 map,并指定了 geoIndex 与第一个地理坐标系对应,数据为空数组(data: []),因为我们主要展示地图而非具体数据点。
配置具体选项
const option = {
  // 工具提示配置
  tooltip: {
    show: true, // 是否显示工具提示
    triggerOn: 'mousemove', // 触发类型,可选值:'mousemove'、'click'
    padding: [4, 8], // 提示框内边距
    borderWidth: 1, // 提示框边框宽度
    borderColor: '#409eff', // 提示框边框颜色
    backgroundColor: 'rgba(255,255,255,0.7)', // 提示框背景颜色
    textStyle: {
      color: '#000000', // 提示框文字颜色
      fontSize: 13, // 提示框文字大小
    },
    formatter: function (e) {
      return e.name; // 格式化提示框显示内容
    },
  },
  // 地理坐标系配置
  geo: [
    // 第一层
    {
      map: 'china', // 地图类型
      z: 3, // z层级
      zoom: 1.2, // 缩放比例
      aspectScale: 0.85, // 宽高比
      roam: false, // 是否开启缩放和平移
      top: '10%', // 距离顶部的距离
      layoutSize: '100%', // 保持地图宽高比
      regions: [
        {
          // 隐藏南海诸岛,因为顶层已经添加过了
          name: '南海诸岛',
          itemStyle: {
            borderWidth: 0.5, // 边框宽度
            shadowBlur: 0, // 阴影模糊程度
            borderColor: '#61aacb', // 边框颜色
            areaColor: '#104584', // 区域颜色
          },
        },
      ],
      itemStyle: {
        borderColor: '#c8feff', // 边框颜色
        borderWidth: 0.5, // 边框宽度
        shadowBlur: 3, // 阴影模糊程度
        shadowColor: '#66edff', // 阴影颜色
        areaColor: '#0862db', // 区域颜色
      },
      emphasis: {
        itemStyle: {
          shadowBlur: 10, // 阴影模糊程度
          borderWidth: 1, // 边框宽度
          areaColor: '#2da9ff', // 区域颜色
        },
        label: {
          show: false, // 是否显示标签
          color: '#ffffff', // 标签颜色
        },
      },
      select: {
        itemStyle: {
          shadowBlur: 10, // 阴影模糊程度
          borderWidth: 1, // 边框宽度
          areaColor: '#2da9ff', // 区域颜色
        },
        label: {
          color: '#ffffff', // 标签颜色
        },
      },
    },
    // 第二层
    {
      map: 'china', // 地图类型
      z: 2, // z层级
      zoom: 1.2, // 缩放比例
      aspectScale: 0.85, // 宽高比
      roam: false, // 是否开启缩放和平移
      silent: true, // 是否静态
      top: '10%', // 距离顶部的距离
      layoutSize: '100%', // 保持地图宽高比
      regions: [
        {
          // 隐藏南海诸岛,因为顶层已经添加过了
          name: '南海诸岛',
          itemStyle: {
            opacity: 0, // 透明度,为0时不绘制该图形
          },
          label: {
            show: false, // 是否显示标签
          },
        },
      ],
      itemStyle: {
        borderColor: '#d8feff', // 边框颜色
        borderWidth: 3, // 边框宽度
        shadowBlur: 10, // 阴影模糊程度
        shadowColor: '#22a1ff', // 阴影颜色
        areaColor: '#0862db', // 区域颜色
        shadowOffsetX: 0, // 阴影水平偏移
        shadowOffsetY: 8, // 阴影垂直偏移
      },
    },
    // 第三层
    {
      map: 'china', // 地图类型
      z: 1, // z层级
      zoom: 1.2, // 缩放比例
      aspectScale: 0.85, // 宽高比
      top: '11.5%', // 距离顶部的距离
      silent: true, // 是否静态
      layoutSize: '100%', // 保持地图宽高比
      itemStyle: {
        borderColor: '#c8feff', // 边框颜色
        borderWidth: 1, // 边框宽度
        shadowBlur: 0, // 阴影模糊程度
        shadowColor: '#99c4ff', // 阴影颜色
        areaColor: '#4ebaff', // 区域颜色
      },
      regions: [
        {
          // 隐藏南海诸岛,因为顶层已经添加过了
          name: '南海诸岛',
          itemStyle: {
            opacity: 0, // 透明度,为0时不绘制该图形
          },
          label: {
            show: false, // 是否显示标签
          },
        },
      ],
    },
    // 第四层
    {
      map: 'china', // 地图类型
      z: 0, // z层级
      zoom: 1.2, // 缩放比例
      aspectScale: 0.85, // 宽高比
      top: '12%', // 距离顶部的距离
      silent: true, // 是否静态
      layoutSize: '100%', // 保持地图宽高比
      itemStyle: {
        borderColor: '#66edff', // 边框颜色
        borderWidth: 2, // 边框宽度
        shadowBlur: 20, // 阴影模糊程度
        shadowColor: '#4d99ff', // 阴影颜色
        areaColor: '#1752ad', // 区域颜色
        shadowOffsetX: 0, // 阴影水平偏移
        shadowOffsetY: 8, // 阴影垂直偏移
      },
      regions: [
        {
          // 隐藏南海诸岛,因为顶层已经添加过了
          name: '南海诸岛',
          itemStyle: {
            opacity: 0, // 透明度,为0时不绘制该图形
          },
          label: {
            show: false, // 是否显示标签
          },
        },
      ],
    },
  ],
  // 系列配置
  series: [
    // 地图
    {
      type: 'map', // 图表类型
      geoIndex: 0, // 地理坐标系索引
      data: [], // 数据
    },
  ],
};

法一总结

在这个示例中,我们首先引入 ECharts 库和中国地图 JSON 数据。然后,我们创建了一个名为 chinaMapRef 的 ref,用于获取地图容器的 DOM 元素。我们还创建了一个名为 chinaInstance 的 shallowRef,用于存储 ECharts 实例。

在 onMounted 生命周期钩子中,我们初始化 ECharts 实例并设置配置选项。我们使用 useEchartsResizeAndDestory 自定义的组合式 API 钩子来处理地图容器的大小变化和组件的销毁。

Top2:通过使用echarts-gl扩展实现3d立体效果

 安装 ECharts 和 ECharts GL

确保你的项目中已经安装了 ECharts 和 ECharts GL。如果没有安装,可以通过以下命令进行安装:

Bash
1npm install echarts echarts-gl
2# 或者使用 yarn
3yarn add echarts echarts-gl

安装完成之后相同的配置就不在重复叙述了,直接进入正文关于ECharts GL的配置信息以及option详文

3D地图配置(geo3D)

  • 基础配置map: "china" 指定地图类型为中国地图;roam: true 允许用户自由旋转和平移地图视图。
  • 视觉效果:通过 itemStyle 控制地图块的颜色、透明度、边框等,创建出统一的视觉风格。
  • 视角控制viewControl 配置允许细粒度控制用户的观察视角,包括自动旋转、旋转范围、观察距离等,增强交互体验。
  • 高亮效果:在 emphasis 下定义移入地图块时的样式,包括标签显示、颜色变化等,提高用户交互反馈。
  • 光照与阴影:通过 light.main 和 light.ambient 配置光照属性,增加地图的立体感和真实感。
  • 标签显示label 配置控制地图上各区域的标签显示方式,包括位置、颜色、字体大小等。
const option = {
  tooltip: {
    show: true,
  },

  //3D地图配置项
  geo3D: {
    map: "china",
    roam: true,
    itemStyle: {
      color: "#007aff",
      opacity: 0.8,
      borderWidth: 0.4,
      borderColor: "#000",
      // areaColor: '#fff'
    },
    viewControl: {
      autoRotate: true, //自动旋转
      autoRotateAfterStill: 3, //停止旋转,单位秒,设置时间内未进行交互操作,将开始自动旋转
      distance: 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 ]
    },

    emphasis: {
      disabled: true, //是否可以被选中
      label: {
        //移入时的高亮文本
        show: true,
        color: "#333", //显示字体颜色变淡
        fontSize: 18, //显示字体变大
      },
      itemStyle: {
        color: "#ff7aff", //显示移入的区块变粉色
      },
    },
    label: {
      show: true,
      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,
      },
    },
  },
  series: [],
};

top2总结

通过以上步骤,我们成功创建了一个基于 ECharts GL 的3D中国地图,还支持用户交互操作,如旋转。同时你还可以在此基础上增加其他的场景配置。

上面的两个demo示例都整理在我的仓库,方便后期使用直接cv:仓库