25年过去了,Brooks博士著名的“没有银弹”的论断依旧没有被冲破。
HTML5也是一样。
但这并不妨碍HTML5是一个越来越有威力的“炸蛋”:发展迅速、势不可挡。
随着HTML5技能的遍及,用HTML5做可视化呈现的项目越来越多了。
HTML5的上风明显:网页上直接运行无需插件、手机平板方便兼容、代码开拓和掩护相对随意马虎,等等。
一大波一大波的做Java、.NET乃至C++桌面的程序老手们都纷纭开始研究javascript了,而初出茅庐的新一代程序猿更是当仁不让的直奔HTML5这个技能大热点而来。

HTML5涵盖的技能点很多,乃至延伸到了前端、后端、通讯等各个层面。
前真个canvas绘图这块无疑是它的核心内容。
Canvas的API虽然不是很繁芜很强大,但是做一样平常的2d绘图基本都够用了。
基于这些API,一大堆的2d绘图组件纷纭出炉。
Echarts、d3.js都是很不错的项目。
Echarts紧张是chart组件,而d3相对杂一些,很多呈现办法很有创意,值得研究。

概述

html5水墨散开HTML5年夜数据可视化后果一彩虹爆炸图 RESTful API

研究d3的起因是最近有一个项目,用户截了一张效果图让我们用HTML5做一下:

看着很眼熟,搜了一下,觉得便是d3例子中的sunburst效果,程序在这里:

http://bl.ocks.org/mbostock/4063423

看上去彷佛也不难,便是一圈一圈的饼图,把树状构造数据按占比一层一层绘制上去就行了。
以是引起了自己动手做一个的兴趣。
“sunburst”英文里该当是“云开日出”的意思,类似强烈的光芒从云层背后透射出来,不知为何中文里大多把它翻译成“日落”。
比如这把Fender Telecaster吉他型号是Brown Sunburst款,就会被大家翻译成“日落色”。

关于日出和日落更喜好哪一个的问题,网上还真有这样的调查。
故意思的是,选择喜好日落的远多于选择日出的。
日出代表希望,日落代表成熟,都是一种美,哪个更美要看你个人的心境,由于它的俏丽是由心生。
为了不在这个问题上站错对,我们还是给他重新起一个更加响亮霸气的中文名字:“彩虹爆炸图”,怎么样?

仔细研究一下彩虹爆炸图的构造,无非便是一个树形构造,并采取发射状的布局。
节点在中间(也可以认为没有唯一的根,而是一堆根节点环绕在第一圈),一次向外发散排列。
每一个节点有名称、数值。
节点可以按照自身数值在扇区所占比例进行绘制,这样就不用管节点详细数值有多大多小了。

这种图最先是由布朗大学教授John T. Stasko设计。

http://www.cc.gatech.edu/~john.stasko/

经由一天的折腾,终于做出了一个还算过得去的“彩虹爆炸图”。
先上个图看看:

紧张功能包括了:

可以通过json来定义数据和样式(类似百度的echarts那样);

颜色可以固定,也可以自动彩虹色;

自动打算数值及角度占比;

动态显示导航路径;

鼠标动态高亮显示路径;

动画飞入、展开导航路径;

笔墨显示及角度掌握;

全矢量,可鼠标缩放、平移,不失落真;

下面重点码一下折腾过程中的几个重点:

一、定义节点工具

首先定义每一个小扇片节点。
每个扇片可以用一段饼图来绘制。
为了大略方便,这里用了最大略高效偷

其余还有笔墨等内容。
以是定义它的json构造大概如下:

var item = {name: '名称', color: 'red', angle: '45', …};

此外,下一圈的数据,可直接定义为这个节点的“孩子节点”,直接在item中定义一个data的子节点数据:

var item = {name: '名称', color: 'red', angle: '45', data:[

{name:’孩子一’, color:’green’,…},

{name:’孩子二’, color:’yellow’,…},

]};

这样就可以组成一个树状构造。
接下来要在canvas上绘制图形了。
为了方便,这里直策应用了矢量图进行定义:

twaver.Util.registerImage('node', {

v: [{

shape: 'circle',

r: ...

lineColor: function(data,view){return data.getClient(\"大众lineColor\公众);},

lineWidth: ...

startAngle: ...

endAngle: ...

},{

shape: 'text',

textBaseline: 'middle',

textAlign: ...

text: ...

x: ...

y: ...

font: ...

fill: ...

rotate: ...

visible: ...

shadow: ...

}],

});

矢量图中定义了2个图形元素:一个arc弧线、一个笔墨工具,分别用于画node和绘制其笔墨。
颜色、字体、是否可见、阴影、对齐、位置、线宽、角度…等等均在上面的定义中用一个function动态获取。
例如,这个节点的半径,通过下面的方法,就可以在图形的lineColor属性中保存并驱动,须要修正,直接修正lineColor这个client属性即可,而不用去修正绘图参数,非常方便:

r:function(data,view){return data.getClient(\公众lineColor\"大众);}

这里有一个比较啰嗦的地方是:每个扇片的角度须要根据每个item定义的原始值进行打算角度占比。
而且,对付太小的扇片,可以给一定的最小值(例如 1度),担保能视觉上看到它。
否则,显示10000和1两个数值,由于比拟过大,可能就杯具了,由于1连1度都占不到,显示效果会非常差。
还有,每个扇片之间该当只管即便留有一定的空隙。
如果连续绘制,就会连成一片,没有“分片”感。
这些可以在代码中进行大略掌握。

二、笔墨掌握

笔墨掌握也比较啰嗦。
首先是对齐办法。
最大略的办法当然是让笔墨在所在扇片处,直接居中、旋转。
这样笔墨会在径向的中间位置,如下图:

但这样显示觉得并不是很完美。
对付中文来说,如果能统一靠近圆心方向的位置对齐,会更好看一些。
这样,纵然笔墨过长,也会向外延伸,不会和里面的重叠。
如下图:

还有,当笔墨在左半圆时,如果不做分外处理,笔墨旋转会导致笔墨大头朝下,阅读起来有把脖子歪断的风险。
以是该当动态判断,如果笔墨在左侧,该当笔墨再增加旋转180度。
同时左侧的笔墨对齐也要分外考虑,该当变成右对齐,才能保持径向的整洁同等。

笔墨还有一个细节便是颜色和阴影的问题。
不该用阴影,纯挚的利用颜色(例如白色),则在一些方向上的节点的笔墨会看不清楚,由于我们做的是彩虹爆炸图,各个方向颜色都不一样,而且还会随着圈数增加而变浅色彩,以是险些不可能用一个固定的颜色(例如白色或玄色)能担保笔墨在所有地方都能和node颜色搭配并看清楚。
以是思来想去还是利用了阴影效果。

遐想了一下我们看美剧时候的字幕,彷佛也是同样的问题。
视频字幕要显示在千变万化的视频场景里面,视频场景的颜色完备随机涌现无从知晓,要想让字幕看清楚,一定也会想一些办法办理。
我们仔细不雅观察一下视频字幕:

仔细不雅观察,字幕是白色笔墨加了一圈玄色外框,这样就不怕任何场景了。
我们在笔墨定义时也仿照一下,设置阴影和阴影偏移试一试:

fill:'white',

shadow: {

offsetX: 2,

offsetY: 2,

blur: 4,

color: 'black',

},

看一下利用前和利用后的效果比拟:

利用阴影后不但笔墨更清晰了,而且也增加了立体感,效果还是不错的。
下面图显示在运用在节点上的效果:

可见不论什么颜色,都能比较好的勾勒出笔墨轮廓,保持清晰可读。

三、天生彩虹颜色

关于颜色,是一个有趣的话题。
对付广大程序猿来说,颜色是一个既大略又困难的东西。
我们随手就能写下’red’, ‘green’, ‘orange’, ‘yellow’这样的色彩斑斓的颜色,还能担保没有语法缺点;我们还会写’#FF55AA’、’#0c0’、’RGB(0,204,0)’、’ RGB(0%,80%,0%)’这样的各种颜色写法;我们也明白RGBA的含义和用场。
但是,我们很少能把一个demo写的颜色很好看、很搭配。
关于颜色和配色往后再专门谈论。
这里我们只想自动天生一圈彩虹一样的颜色。
用我们熟习的RGB方法彷佛比较困难了。
于是想起了那个HSV的颜色定义方法,它貌似很适宜办理这个问题。

HSV颜色模型定义了色调H、饱和度S和亮度V,由A. R. Smith在1978年创建的一种颜色空间。
个中H用一圈360度表示所有颜色,从赤色开始按逆时针方向打算,赤色为0度。
饱和度S从0到1,越大越饱和。
亮度V从0到255(也可以转换为从0到1,方便利用),越大越通亮,越小越暗淡。

Js里面并没有直接处理HSV颜色的函数。
不过用下面的代码很方便可以从hsv转为rgb:

写一个对应的js函数也很大略:

/ h, s, v (0 ~ 1) /

function getHSVColor(h, s, v) {

var r, g, b, i, f, p, q, t;

if (h && s === undefined && v === undefined) {

s = h.s, v = h.v, h = h.h;

}

i = Math.floor(h 6);

f = h 6 - i;

p = v (1 - s);

q = v (1 - f s);

t = v (1 - (1 - f) s);

switch (i % 6) {

case 0: r = v, g = t, b = p; break;

case 1: r = q, g = v, b = p; break;

case 2: r = p, g = v, b = t; break;

case 3: r = p, g = q, b = v; break;

case 4: r = t, g = p, b = v; break;

case 5: r = v, g = p, b = q; break;

}

var rgb='#'+toHex(r 255)+toHex(g 255)+toHex(b 255);

return rgb;

}

再回到我们的彩虹爆炸图。
每一个节点对应的所在角度(中央角度)决定了它自己的颜色值。
以是,我们可以直接根据这个角度得到颜色的h。
然后,为了让彩虹逐渐一圈一圈变淡,再把s饱和度从1逐圈递减(例如0.1),产生变淡的效果。
为了防止圈太多末了看不清,减到0.2到0.3旁边可以停滞递减。

var fromAngle=node.getClient(‘fromAngle’);

var toAngle=node.getClient(‘toAngle’);

var level=node.getClient(‘level’);//节点在第几圈

var h = (fromAngle+to)/2 % 360 /360; //中央角度,并转换为弧度

var s = Math.max(0.2, 1-level0.1);//每圈s递减0.1,直到0.2为止

var v=1;

var color=getHSVColor(h, s, v);

这样就得到了一圈颜色。
实验效果如下:

如果相对某个节点的颜色做分外处理,例如逼迫为橙色来凸显,我们可以在数据中定义时加个标记,设置颜色时候直策应用而不用打算即可。

{name:'浦东新区', value: 2600, color: '#FE9A2E'}

接下来要实现鼠标划过节点,自动打算路径、高亮路径节点、暗淡非路径节点。
为了方便路径探求,程序把每个节点的下一圈子数据定义为子节点,子节点通过getParent函数可以直接得到父工具。
这样,通过不断getParent就可以得到全体路径上的节点,并修正其颜色为预设颜色,实现高亮效果:

var node=highlightedNode;

while(node){

node.setClient(‘color’, node.getClient(‘color.original’));

node=node.getParent;

}

对付非路径节点的颜色,可以设置为预设颜色但饱和度为0.1的浅色彩 ,让它变淡,以便突出高亮路径:

var color = getHSVColor(h, 0.1, v);

node.setClient(‘color’, color);

四、动画效果

末了,为了图形更生动,利用了一些动画效果。
首先想到的便是图形出来时候,用动画从小到大发散开来,会很动感。
这样做须要用动画函数来驱动每一个节点的半径位置,从0增加到所在的半径位置,如果大家一起设置,全体图就会动起来。
这里用了一个动画函数来驱动,并利用了网上常用的easing函数来掌握,避免线性的动画太去世板:

new Animate({

from: 0,

to: 1,

dur: 3000+level100,

easing: 'elasticOut',

onUpdate: function (value) {

node.setLocation('pie.location’, value);

},

}).play;

上面定义的动画,用3秒钟跑完,用'elasticOut'的easing办法。
每一帧,修正node的位置信息。
这样就完成了橡皮筋一样的环形弹出散开效果。

其余,导航条的出来也比较突兀,这里也利用一下动画,让它从左到右逐步伸出:

new Animate({

from: {x:x1, y:y1},

to: {x:x2, y:y2},

delay:50,

type: 'point',

dur: 1000,

easing: 'bounceOut',

onUpdate: function (value) {

node.setCenterLocation(value.x, value.y);

和上一个动画的不同之处在于这里利用了{x、y}的point构造,每一帧直接更新节点位置。
同时设置了50毫秒的delay,让动画有一点点粘性结束,不至于太突兀。
效果不错。

至此,彩虹爆炸图基本上就做的差不多了。
利用起来也很大略,只要准备一些json数据就可以了,下面是一些有趣的数据做出来的效果。
感兴趣的同学可以到这里索取代码。

实际运用在项目中的示意图。
如果你也希望项目中用一下彩虹爆炸图,欢迎给我发邮件索取:info@servasoft.com

扫推举微信:中国大数据

推举情由:一手新鲜,绝对干货