我们都知道,echarts 是百度开源的一个可以方便数据可视化呈现的一种图表,使用起来很方便,因此,对于一些定制程度不是很高的场景,我们直接用 echarts,可以快速成型我们的产品。
但是相对于 echarts 2d 图表来说,3d 的图表使用的人就少很多了,因此文档也不是很丰富,有时候碰到问题,也不是很容易找到解决方案。
因为本身就是一枚前端数据可视化工程师,所以在工作中,难免会用到各种 3d 框架,因此对于一些基本的 3d 概念,还是有所了解的。
因为 ECharts GL 提供了很好的 3d 图表,因此之前就直接在项目中拿来用了,但是最近客户反馈说,这个图的效果不太好,因为每次进去,位置都不太合适,需要手动拖动一下,才能勉强调整成这样:
image.png可以看到的是,右边有很大一个空白的区域,这个图也就占用了整个视口一半的面积。
我心想,这改起来应该挺容易的吧,毕竟 3d 里面,物体的大小位置确定的情况下,调整下镜头参数就能从不同的角度看物体。
出于一个程序员的直觉,第一反应就是找官方文档,找找看有没有调节的方法。
确实是有,但是用起来好像并不是那么的方便,就是在下面这个页面里面:https://www.echartsjs.com/option-gl.html#grid3D.viewControl
可以在配置项里,改变对应的属性,进行手动调整。但是又有个问题来了,这位置调整起来多不方便,我要调整到猴年马月才能调到合适的位置去啊。
于是我只得上 github 官方仓库的 issue 看看有没有人提到同样的问题,有没有热心的吃瓜群众给出好的解决方案。
我粗略的扫了一眼 issue,又搜了一下,或许是我关键字给的不太对,并没有找到跟我有一样烦恼的吃瓜群众,这就难办了。
但是我又不想继续手动调整,这难道只能研究源码了,从源码的层面去解决了么?但是这工作量有点大了,毕竟研究别人的代码并没有那么容易,何况还是个成熟的开源的框架。
其实我还是打算打开源码研究一下的,研究了半个小时未果,遂放弃了。
后来我灵机一动,echarts 里面不是根据 option 来生成图表的么?那如果我先在图上调整好位置,然后通过 charts.getOption() 方法获取 option,那么这个 option 里面的配置,是不是我调整好位置后的参数配置呢?
之所以有这么个想法,纯粹是出于惯性思维。
因为我们公司自己研发的 3d 引擎里面,就提供了现成的 api 可以获取到实时的镜头参数。但是在 echarts 里面没有的话,显然很不合理啊。
于是立刻开始尝试:
首先将 echarts 实力在控制台打出来,然后打开场景,填入数据,再拿到打印出的变量,调用 getOption api,获取 option。
可以看到的是,获取到的 grid3D 对象的属性是这样的:
[
{
"boxWidth": 50,
"boxDepth": 500,
"viewControl": {
"distance": 400,
"alpha": 3.069606211544383,
"beta": 45.74964692390633,
"minDistance": 40,
"maxDistance": 400,
"rotateSensitivity": [
1,
0
],
"zoomSensitivity": 1,
"panSensitivity": 1,
"panMouseButton": "middle",
"rotateMouseButton": "left",
"orthographicSize": 150,
"maxOrthographicSize": 400,
"minOrthographicSize": 20,
"center": [
-113.52360803563104,
-11.605600586260213,
18.02255622141436
],
"minAlpha": -90,
"maxAlpha": 90,
"autoRotate": false,
"projection": "perspective",
"autoRotateDirection": "cw",
"autoRotateSpeed": 10,
"autoRotateAfterStill": 3,
"damping": 0.8
},
"light": {
"main": {
"intensity": 1.2,
"shadow": true,
"alpha": 30,
"beta": 40,
"shadowQuality": "high",
"color": "#fff"
},
"ambient": {
"intensity": 0.75,
"color": "#fff"
},
"ambientCubemap": {
"texture": null,
"exposure": 1,
"diffuseIntensity": 0.5,
"specularIntensity": 0.5
}
},
"splitLine": {
"show": true,
"lineStyle": {
"opacity": 0.5,
"color": [
"#ccc"
],
"width": 1,
"type": "solid"
}
},
"show": true,
"zlevel": -10,
"left": 0,
"top": 0,
"width": "100%",
"height": "100%",
"environment": "auto",
"boxHeight": 100,
"axisPointer": {
"show": true,
"lineStyle": {
"color": "rgba(0, 0, 0, 0.8)",
"width": 1
},
"label": {
"show": true,
"formatter": null,
"margin": 8,
"textStyle": {
"fontSize": 14,
"color": "#fff",
"backgroundColor": "rgba(0,0,0,0.5)",
"padding": 3,
"borderRadius": 3
}
}
},
"axisLine": {
"show": true,
"lineStyle": {
"color": "#333",
"width": 2,
"type": "solid"
}
},
"axisTick": {
"show": true,
"inside": false,
"length": 3,
"lineStyle": {
"width": 1
}
},
"axisLabel": {
"show": true,
"inside": false,
"rotate": 0,
"margin": 8,
"textStyle": null,
"fontSize": 12
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.3)",
"rgba(200,200,200,0.3)"
]
}
},
"postEffect": {
"enable": false,
"bloom": {
"enable": true,
"intensity": 0.1
},
"depthOfField": {
"enable": false,
"focalRange": 20,
"focalDistance": 50,
"blurRadius": 10,
"fstop": 2.8,
"quality": "medium"
},
"screenSpaceAmbientOcclusion": {
"enable": false,
"radius": 2,
"quality": "medium",
"intensity": 1
},
"screenSpaceReflection": {
"enable": false,
"quality": "medium",
"maxRoughness": 0.8
},
"colorCorrection": {
"enable": true,
"exposure": 0,
"brightness": 0,
"contrast": 1,
"saturation": 1,
"lookupTexture": ""
},
"edge": {
"enable": false
},
"FXAA": {
"enable": false
}
},
"temporalSuperSampling": {
"enable": "auto"
}
}
]
找到 viewControl 对象:
{"viewControl": {
"distance": 400,
"alpha": 3.069606211544383,
"beta": 45.74964692390633,
"minDistance": 40,
"maxDistance": 400,
"rotateSensitivity": [
1,
0
],
"zoomSensitivity": 1,
"panSensitivity": 1,
"panMouseButton": "middle",
"rotateMouseButton": "left",
"orthographicSize": 150,
"maxOrthographicSize": 400,
"minOrthographicSize": 20,
"center": [
-113.52360803563104,
-11.605600586260213,
18.02255622141436
],
"minAlpha": -90,
"maxAlpha": 90,
"autoRotate": false,
"projection": "perspective",
"autoRotateDirection": "cw",
"autoRotateSpeed": 10,
"autoRotateAfterStill": 3,
"damping": 0.8
},}
可以看到,center 就是当前镜头看向的目标点,alpha 就是垂直转角,beta 就是水平转角。
这里可以看大,其实他于一般的 3d 框架里面还是有点区别的,这里好像并没有镜头的概念,镜头都是固定死的,然后通过设置 center,alpha,beta 等相关参数去控制。
但是究竟是不是我们想的这样子的呢?试过了才知道,才有发言权嘛。
于是将这段配置拷到我们代码的配置里面去,怀着忐忑的心情刷新页面,映入眼帘的果然就是我们之前调整好的效果:
image.png可以说这种方式就很赞了,但是还缺乏点自动化的功能,如果每次都这么手动的去调整,接下来再手动的获取相关参数,那岂不是累死了。
于是我们稍微搭配上一个工具 —— dat.gui,来辅助我们调整。
const viewControl = this._option.grid3D.viewControl;
const gui = new dat.GUI({ name: 'My GUI' });
gui.add(viewControl, 'alpha', -90, 90)
.onChange((val) => {
chart.setOption(this._option);
})
.name('alpha');
gui.add(viewControl, 'beta', -180, 180)
.onChange((val) => {
chart.setOption(this._option);
})
.name('beta');
下面是小工具的样式:<br />
image.png
调整起来果然很方便,也能实时的知道目前 alpha 和 beta 值是多少了。
如果你没用过 dat.gui,可以参考一下 https://github.com/dataarts/dat.gui,有源码,有示例,有文档。
刚才看了眼 echarts 的配置文档,里面有对 alpha 和 beta 的说明,可能比我解释的要详细些,现在直接贴到这里来了:
image.png
网友评论