前言--书接上文,我们用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官方提供了两个控制层级的属性:zlevel
和z
。其中最主要的区别就是zlevel
会重新创建一个canvas画布,如果用过echarts的伙伴应该知道,当echarts中图表过多时,加载就会变慢。原因就是每个echarts图表其实就是一个canvas画布,而创建画布是需要时间的,如果层级很多的话,那么地图的加载就会很慢,甚至网络慢的情况下,层级会很明显地一个个显示出来,这样的效果十分差的。
估计echarts官方也发现了这个问题,所以提出了z
来控制层级,它的好处就是不会创建新的canvas画布,那么这里我就使用z
来控制层级。
虽然地图已经有了层级效果,但是不足就是效果太明显了,3D的视觉效果很假。例如上面的示例中,能够很明显的看出来有三个不同层级的地图。为此我的解决方案就是,将中间的地图模糊化,这样中间看起来就像是最上面的地图的投影,而不是一个地图。
这里用到的属性就是模糊四件套shadowOffsetX
、shadowOffsetY
、shadowBlur
、shadowColor
。
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的坐标系统)