美文网首页
ECharts GL 镜头参数的调整方法

ECharts GL 镜头参数的调整方法

作者: 纯爱枫若情 | 来源:发表于2019-08-02 14:48 被阅读0次

    我们都知道,echarts 是百度开源的一个可以方便数据可视化呈现的一种图表,使用起来很方便,因此,对于一些定制程度不是很高的场景,我们直接用 echarts,可以快速成型我们的产品。

    但是相对于 echarts 2d 图表来说,3d 的图表使用的人就少很多了,因此文档也不是很丰富,有时候碰到问题,也不是很容易找到解决方案。

    因为本身就是一枚前端数据可视化工程师,所以在工作中,难免会用到各种 3d 框架,因此对于一些基本的 3d 概念,还是有所了解的。

    因为 ECharts GL 提供了很好的 3d 图表,因此之前就直接在项目中拿来用了,但是最近客户反馈说,这个图的效果不太好,因为每次进去,位置都不太合适,需要手动拖动一下,才能勉强调整成这样:

    image.pngimage.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.pngimage.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.pngimage.png

    调整起来果然很方便,也能实时的知道目前 alpha 和 beta 值是多少了。

    如果你没用过 dat.gui,可以参考一下 https://github.com/dataarts/dat.gui,有源码,有示例,有文档。

    刚才看了眼 echarts 的配置文档,里面有对 alpha 和 beta 的说明,可能比我解释的要详细些,现在直接贴到这里来了:

    image.pngimage.png

    相关文章

      网友评论

          本文标题:ECharts GL 镜头参数的调整方法

          本文链接:https://www.haomeiwen.com/subject/peyldctx.html