数据可视化之MarkPoint

MarkPoint是什么效果?如上图,一闪一闪亮晶晶的效果,这是在Echarts中对应的效果。我最早看到的是腾讯的一个Flash的版本,显示当前QQ在线人数的全国分布效果,感觉效果很炫,当时也在想,怎么用JS,HTML5来做出类似的效果,但说实话,没什么思路,甚至怀疑JS是否做不出来这种逼真的效果来。终于看到Echarts中提供了这个功能。下面就扒开她绚丽的衣着,一起走进MarkPoint的世界。

数据

首先还是先看看数据上的逻辑。上图是一个数据格式,placeList包括每一个关键点的名称和坐标位置,而在风格中主要有name,可以设置为强中弱三种,分别对应MarkPoint图中白蓝绿三种效果,类型是中国地图,而具体的风格在存储在markPoint字段中。我们在看看markPoint字段里面是什么内容。

如上就是markPoint里面的主要内容,这里,每一个点是一个钻石(diamond)的样式,符号大小,还有一个effect的属性,这就是它的动画风格,而data则用来加载placeList的信息。

综上所述,对于使用者而言,指定好要显示markPoint的位置,也就是placeList,然后在赋予它们的具体效果,中国范围,强弱类型以及具体的形状(钻石,矩形或圆形等),这样就可以得到MarkPoint这样的闪烁效果。

原理

其实说原理有点夸大其词。通过数据层面,可以看出来每一个点都是独立的,如果你放大后,基本可以判断出来各自完成自己的动画效果,并一致循环下去。如果缩小后,你会发现所有的markPoint并不是同步的,频率各不相同,显得杂乱无章。(推荐TED的视频:The First Secret of Great Design - Tony Fadell - TED Talks)。

这样,这个问题就分解成了两个部分:

  • 如何模拟每一个点的闪烁效果
  • 如何管理大规模的点的闪烁周期

闪烁效果的实现

如上,是同一个markPoint在不同帧下的效果,大家可以想想一下这样一个从小到大然后再到小的过程,则完成了闪烁的效果,如果你足够细心会发现里面有一个blur的平滑效果,这样会让闪烁有一个平滑的效果,类似字体的抗锯齿,看起来有一种朦胧的感觉。当然,blur这个效果是怎么实现的?其实在之前风向图和热点图中都采用了这个技术,就是和上一帧的图片进行一个半透明的叠加。然后在配合一个动画特效(animation effect),闪烁的效果就完成了。

多点闪烁动画的实现

如上是在某一帧的截图。俗话说的好,一花独放不是春,所以如何控制这么多的点,风格各不相同的markPoint,而且频率各不相同,这就涉及到动画类和随机数之间的内容,同时在框架上能够贯穿整个渲染周期。

我们看一下在Echarts上的流程,先是初始化的流程:

如同,MarkPoint的数据初始化主要是Map类读取数据,然后在Base中调用getLargeMarkPointShape来创建这些点。

在Base中,调用animationEffect指定单个MarkPoint的闪烁风格,这里需要额外说明一下,虽然在数据中动画风格只是简单的show:true.但实际上,最终是采用的config.js中默认的动画风格,比如周期,是否循环,跳动等,如下图所示:

而在ecEffect中,调用largePoint来随机设置,实现各自不同的动画周期。从而完成整改初始化的过程。

初始化结束后,则进入到了渲染阶段。渲染是采用的zrender框架,而markPoint则是由Animation来驱动,每一帧都会调用update,在onframe中来设置每一个点当前的状态,比如大小,根据时间周期下,线性插值计算出它应该的大小(下面会详细说明),最后调用Symbol::buildPath实现所有markPoint的闪烁效果。

这就是初始化准备和渲染周期的大致一个过程,下面对主要功能模块进行介绍

实现代码

如上,只是指定了blur为true,则实现了平滑效果,简单不?其实这用了一个双缓存的技术,在zrender中有一个Layer对象,每一帧都会叠加上一帧的效果,并保存。具体的实现可以参阅zrender的Layer类,比较简单。

闪烁动画有点复杂,首先,怎么控制一个markPoint从大到小的这样一个线性变换的过程,动画类是如何控制的,另外对于不同的markPoint,有这么多点,同一帧下每个点对应的风格也不尽相同,这又是如何控制的。

首先,这要介绍一下zrender中的Animation类,一个非常好用强大的类,先看看使用代码,如下:

首先,这是一个when.js风格的使用方式,该动画主要用来控制effectShape的‘style’属性,即每一帧来对style属性进行更新。那更新什么内容呢?这就是clip对象了。

这里有四个when,再加上最上面的随机的初始大小,也就是说一个周期有5个控制点,其中clip1 = 100,而clip2 = 0,,这里对应的是该控制点对应markPoint的size的百分比。也就是在这个周期中,按照如下的插值算法来控制该点的size。不知道说清楚了没有,可以自己调试一下代码看看。

这是在一帧下插值计算当前size的百分比,这里采用的线性插值,还有其他多种算法可以选择,这里是size,所以用的最简单的线性插值,你也可以实现轨迹,或者加速度等不同的公式来实现对应的效果。

插值计算完了,付给对应的style中randomMap+i属性上。这里,一共常见了20个Animation类,这样就会有20个动画效果,来实现频率各自不同的闪烁效果。最后会调用zrender的refresh,最终来到Symbol的渲染阶段。这里,每一个点根据自己的索引选择对应的缩放比例percent,然后进入下面的绘制阶段。

另外,在对每一个点的渲染函数中,进行了进一步的优化,代码如下,根据大小进行了简化。

Ok,到此,我想到的关于MarkPoint的内容都已经完毕,另外这个类涉及到一个大规模点渲染,等有机会对这方面详细研究后在和大家分享。

原文发布于微信公众号 - LET(LET0-0)

原文发表时间:2016-01-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据小魔方

think-cell chart 系列1——堆积柱形图!

今天正式开始跟大家分享之前介绍过的图表插件——think-cell chart 。 要讲的第一个图表类型是其自带图表库中的第一个图表——堆积柱形图。 在正式开始...

7046
来自专栏前端小作坊

CSS硬件加速的好与坏

每个人都痴迷于60桢每秒的顺滑动画。为了实现这个顺滑体验现在用的最流行的一个做法就是使用『CSS硬件加速』。在一些极端例子中,强制使用translate3d意味...

1032
来自专栏我有一个梦想

UE4新手编程之创建空白关卡和添加碰撞体

让我们接着上次继续学习UE4引擎,今天我们学习下怎样创建空白的关卡以及添加碰撞物体。 一. 创建空白关卡 1) 点击文件 -> 新建关卡(或者按快捷键Ctrl+...

2959
来自专栏walterlv - 吕毅的博客

UWP 将图片裁剪成圆形(椭圆)

2018-06-15 13:21

1671
来自专栏点滴积累

Cesium基础使用介绍

前言 最近折腾了一下三维地球,本文简单为大家介绍一款开源的三维地球软件——Cesium,以及如何快速上手Cesium。当然三维地球重要的肯定不是数据显示,这只是...

1.9K6
来自专栏小壮和前端

手写贪吃蛇

1773
来自专栏GIS讲堂

当我们遇到问题的时候改如何解决

问题 在Openlayer3中直接加载PNG图片,在API中提供了ImageStatic可以将图片展示出来,但是如何设置图片的imageExtent让图片能...

1762
来自专栏数据的力量

我们来做瀑布图

1453
来自专栏陈满iOS

iOS图形处理概论:OpenGL ES,Metal,Core Graphics,Core Image,GPUImage,Scene Kit (3D) ,Sprite Kit (2D),OpenCV

对于刚接触iOS图形相关框架的小白,有一些图形框架在字面上和功能上非常容易混淆。这里旨在总结一下各种框架,区分它们的概念和功能,以作日后进一步细分学习的指引。因...

3673
来自专栏BestSDK

表格设计的六种打开方式,正确提升表格的阅读效率

在设计数据类产品、后台配置产品时,PD 常常会指着一块地方说「这儿放个表格,需要有balabala…」,而表格的结构不外乎这几种类型: 垂直布局 水平布局 矩阵...

3145

扫码关注云+社区

领取腾讯云代金券