vue2+echarts实现3D地图

前言--书接上文,我们用vue2+echarts实现了一个基本地图,今天我们就在这个基本的地图上进行改造,让它成为一个3D地图。

参考文章:www.cnblogs.com/beevesnoodl... (canvas的坐标系统)

首先附上最终效果。

其实针对3D的图表模型,echarts也专门推出了一个库echarts-gl来实现,比如3D柱状图、3D折线图、地球等等,它也提供了实现3D地图的功能,但是这个库实现的效果太粗糙了,

这是我从官网的截取的示例,不难看出,在视觉效果上确实很震撼,但是美观程度不高。当然也可以通过书写配置项来达到我们自己想要的效果,但是过程比较繁琐,所以这里我还是用echarts来实现的3D地图。

其实3D相较于2D就是多了立体感,简单来说就是多了一个坐标轴。2D只有两个,那就是X和Y,而3D则是多了一个Z轴。应该都听过点成线、线成面、面成体,所谓的立体图形,其实也就是无数个平面图形推叠在一起实现的。

那么,由此可知,我们也可以将我们的地图想象成一个面,然后将多个地图叠加在一起,就能组合成一个3D地图。所以3D地图的问题也就是在页面上显示多个地图,只要他们不在一个平面上,也就是位置存在上下的关系,那么就可以形成一个3D地图。

在echarts 的配置项中,series是一个数组,一个对象就是一个数据项,那么在我们这里就是一个地图,所以我们只要仿照已经写好的地图,再写几个类似的数据项就能实现效果了。话不多说,开干。直接暴力复制粘贴一份试试效果。

yaml 复制代码
    {
        type: "map", // 设置图表类型为地图
        map: "jingzhouMap", // 地图JSON文件
        roam: false,
        aspectScale: 0.9, // 长宽比
        zoom: 1.32,
        tooltip: {
          show: false,
        },
        label: {
          show: false, // 是否显示对应地名
        },
        layoutCenter: ["50%", "58%"],
          layoutSize: 650,
          emphasis: {
            // 对应的鼠标悬浮效果
            disabled: true,
          },
          select: {
            disabled: true,
          },
          itemStyle: {
            normal: {
              areaColor: "#38b4fc",
              borderColor: "#6dceff",
              borderWidth: 5,
              // 内部阴影
              shadowColor: "rgba(24, 131, 220,0.2)",
              shadowBlur: 8,
              shadowOffsetY: 0, // 阴影在Y轴的偏移量
              shadowOffsetX: 0, // 阴影在X轴的偏移量
            },
            emphasis: {
              disabled: true, // 是否可以被选中
              areaColor: "#38b4fc",
              borderColor: "#6dceff",
              borderWidth: 5,
              // 内部阴影
              shadowColor: "rgba(9, 117, 185,0.7)",
            },
          },
},

这是series中第二个对象,与第一个不同的是我将他的 layoutCenter改为了 layoutCenter: ["50%", "58%"],为的就是想要看看两个地图设置在不同的地方会怎么显示,为了显示不同,那么我们来看看效果。

没有变化,也就是说这种方法是行不通的。原因是series是系列的意思,其中的数据项都是同层级的,也就是同一个平面中的,所以我们不能通过在series中添加地图元素来做到3D的效果。使用series叠加,卒

重新寻找新的方法,通过翻阅文档发现,echarts提供了geo配置项,其代表的是地理坐标系,最重要的一点,他的层级比series要高,也就是说它会显示在series的上层,那么不就是正好满足了我们的需求嘛。那么好,二次开干。代码不变直接写入geo中。

这里我是把上面的代码直接写入geo中,效果如下。

很完美,有明显的层级效果,说明这种方法是可行的,但是效果有点丑陋,需要进一步的更改。这里就得吐槽一句二charts的官网了,因为官网中表明geo是一个对象,但是其实他也是可以作为数组的(这也是我偶然写错代码的情况下发现的)那么,既然可以是数组,就可以接受多个对象,是不是也就可以形成多个地图,开干。

将geo变成一个数组,然后再传入一个map配置项,把layoutCenter改为layoutCenter: ["50%", "50%"],并且将两个地图的底色也进行了改变,以突出两个的不同。代码结构和实现的效果如下。

可以看到,地图有了很明显的层级效果。同时我也发现,geo数组中配置项的层级性与设置的layoutCenter无关,而是与书写的先后顺序有关。例如这里我将["50%","50%"]写在数组的第一项,地图就发生了变化。

可以看出来["50%","50%"]这一项位于整个地图的最下方,那么得出的结论就是,在一般情况下,geo数组中后面的属性层级高于前面的属性。那么为什么是一般情况下呢,因为官网中也给出了相应的分层级的标识,以下为官网内容(这里再次吐槽一下,既然有专门分层级的标识,那也就说明可以书写多个配置项,那岂不是就是说geo也可以是数组,但是官网并没有直接说明)。

可以看出,echarts官方提供了两个控制层级的属性:zlevelz。其中最主要的区别就是zlevel会重新创建一个canvas画布,如果用过echarts的伙伴应该知道,当echarts中图表过多时,加载就会变慢。原因就是每个echarts图表其实就是一个canvas画布,而创建画布是需要时间的,如果层级很多的话,那么地图的加载就会很慢,甚至网络慢的情况下,层级会很明显地一个个显示出来,这样的效果十分差的。

估计echarts官方也发现了这个问题,所以提出了z来控制层级,它的好处就是不会创建新的canvas画布,那么这里我就使用z来控制层级。

虽然地图已经有了层级效果,但是不足就是效果太明显了,3D的视觉效果很假。例如上面的示例中,能够很明显的看出来有三个不同层级的地图。为此我的解决方案就是,将中间的地图模糊化,这样中间看起来就像是最上面的地图的投影,而不是一个地图。

这里用到的属性就是模糊四件套shadowOffsetXshadowOffsetYshadowBlurshadowColor

  • shadowBlur:阴影的模糊度(模糊大小)
  • shadowColor:阴影颜色
  • shadowOffsetX: 阴影水平方向上的偏移距离
  • shadowOffsetY: 阴影垂直方向上的偏移距离

这里直接在layoutCenter为["50%","50"%]中设置如下选项:

yaml 复制代码
...     // 其他代码省略
normal: {
      ...     // 其他代码省略
      shadowBlur: 8,
      borderWidth: 8,
      shadowOffsetY: 50,
      shadowOffsetX: 10,
},
...     // 其他代码省略

需要注意的是,这里的X和Y不是我们普通的直角坐标系,canvas画布用的都是窗口坐标系,其效果如下(该效果图取自下方网站)

这里给大家提供一个链接,里面详细讲了canvas 的坐标系统,有兴趣深入的可以直达 www.cnblogs.com/beevesnoodl...

设置了模糊四件套之后的效果如下

这样似乎看不出效果,我知道你很着急,但是别急,这是因为中间的地图原本就很大,导致阴影效果被遮挡了,因为设置了shadowOffsetY: 50,也就是在原图的下方,原图太大了就挡住了,那么我们来设置layoutCenter为["50%","46%"],再来看看效果

这样看起来效果就比之前好太多了,为了效果更加好看,无非就是在geo里多添加几个地图,然后设置通过设置模糊度和层级来设置景深效果就可以啦,这里就留给大家自己去实现了。最后附上我的效果图。

大家有需要的可以去git中获取源码 gitee.com/guoJunJia/v...

参考文章:www.cnblogs.com/beevesnoodl... (canvas的坐标系统)

相关推荐
安冬的码畜日常44 分钟前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
小白学习日记2 小时前
【复习】HTML常用标签<table>
前端·html
丁总学Java2 小时前
微信小程序-npm支持-如何使用npm包
前端·微信小程序·npm·node.js
yanlele2 小时前
前瞻 - 盘点 ES2025 已经定稿的语法规范
前端·javascript·代码规范
懒羊羊大王呀2 小时前
CSS——属性值计算
前端·css
DOKE3 小时前
VSCode终端:提升命令行使用体验
前端
xgq3 小时前
使用File System Access API 直接读写本地文件
前端·javascript·面试
用户3157476081353 小时前
前端之路-了解原型和原型链
前端
永远不打烊3 小时前
librtmp 原生API做直播推流
前端