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的坐标系统)

相关推荐
中微子4 分钟前
JavaScript 防抖与节流:从原理到实践的完整指南
前端·javascript
天天向上102419 分钟前
Vue 配置打包后可编辑的变量
前端·javascript·vue.js
芬兰y34 分钟前
VUE 带有搜索功能的穿梭框(简单demo)
前端·javascript·vue.js
好果不榨汁41 分钟前
qiankun 路由选择不同模式如何书写不同的配置
前端·vue.js
小蜜蜂dry41 分钟前
Fetch 笔记
前端·javascript
拾光拾趣录43 分钟前
列表分页中的快速翻页竞态问题
前端·javascript
小old弟43 分钟前
vue3,你看setup设计详解,也是个人才
前端
Lefan1 小时前
一文了解什么是Dart
前端·flutter·dart
Patrick_Wilson1 小时前
青苔漫染待客迟
前端·设计模式·架构
写不出来就跑路1 小时前
基于 Vue 3 的智能聊天界面实现:从 UI 到流式响应全解析
前端·vue.js·ui