EasyV中的3D面积图表是怎么实现的?

349 阅读4分钟

以下效果实现来自EasyV数据可视化组件,感兴趣的小伙伴可以点击来试用哦~

最终效果

构建坐标体系

将原始数据处理成适合图表展示的数据结构

为了方便图表的数据对接以及组件样式的配置,组件拿到的原始数据往往不适合可视化效果的展示,需要我们对数据进行初始化的操作

得到适于可视化展示的数据。

原始的数据结构如下

let originData = [

{ x: '05-01', y: 2, s: '系列一' },

{ x: '05-02', y: 30, s: '系列一' },

{ x: '05-03', y: 6, s: '系列一' },

{ x: '05-04', y: 8, s: '系列一' },

{ x: '05-05', y: 10, s: '系列一' }

]

经过处理的数据结构如下

let data = [

{x: 0, y: 2, label: '05-01'},

{x: 2, y: 30, label: '05-02'},

{x: 4, y: 6, label: '05-03'},

{x: 6, y: 8, label: '05-04'},

{x: 8, y: 10, label: '05-05'}

]

借用d3.js的数学方法映射数值

D3.js是成熟的数据可视化工具函数库,提供了很多有用的数学函数,能对数据可视化带来很大的帮助。在本组件的开发中主要使用D3.js做数据值域和图表尺寸定义域的映射。将数据值的绝对值在3D场景中体现为相对值。

定义域和值域的范围

构建定义域和值域的比例尺

构建数据对象在x轴和y轴上的分段

使用Line2构建有粗细的轴线段

three.js的line对象本身并不支持宽度的设置,需要使用Lin2插件来构建支持宽度的线段。

使用精灵贴图构建轴标签

根据设计师的要求,轴标签需要始终面向相机,因此使用精灵贴图 来实现标签的制作。

构建模糊镜面

1、使用Reflector.js构建基础镜面

2、在Reflector的shader中增加高斯模糊

使用Reflector插件生成的默认镜面并不会产生默认的镜面效果,因此需要在修改插件中的shader源码,这里我们使用高斯模糊产生模糊效果。

在shader中我们可以修改重复绘制的次数和成都来控制模糊产生的效 果,使之达到我们想要的效果。

在Reflector的shader中修改融合函数

为了达到我们想要的效果,我们修改默认的融合函数以达到我们需要的效果

构建体积

根据处理过的数据构建shape,使用shape对象拉伸几何体

我们通常使用ExtrudeGeometry几何体拉伸出边缘不规则的几何体。首先我们需要根据数据构建不规则边缘的shape形状,然后拉伸shape形状赋予它体积,生成表现形式是3D的面积图。

重新计算拉伸几何体的uv

经过拉伸生成的几何体并没有生成规则的uv,这时候就需要我们重新计算几何体的uv坐标。我们根据几何体的外包围盒重新计算几何体的uv。

构建面积图边缘弧线

我们使用CatmullRomCurve3构建弧线路径,同时使用TubeGeometry来构建弧线。

构建渐变材质, 渐变扫光材质

书写颜色渐变shader、居中渐变shader

面积图的侧面需要用到渐变的材质,面积图的顶面则需要使用居中渐变的材质,这些材质都需要我们在shader中构建。

构建shader动画

为了构建shader的动画,需要我们往shadeMaterial材质中传入变化的时间值。

构建全局的泛光

构建bloom的后期渲染系统

使用UnrealBloomPass绘制后期发光

在UnrealBloomPass中根据亮度提取颜色,单独提取发光光晕

UnrealBloomPass插件会默认将场景的背景渲染成黑色,为了去除通过后处理加上的颜色,我们只能通过修改插件的shader源码来完成。在shader中,我们通过亮度来过滤颜色。

在animate方法中单独添加发光对象的光晕

后处理的过程中会绘制一遍低分辨率对象,因为我们只需要对象的发光部分,所以需要在源码中注释相关代码。为了绘制单独发光的对象,我们需要将需要发光处理的对象放置到单独的渲染层中,并在绘制方法刷新的时候单独绘制发光物体。