基于 HT 实现锅炉火焰动画
前言
本文介绍的是用 HT 驱动 Canvas 实现的一个锅炉的可视化模型,目的在于以一种可视化的方式随时观测炉内燃烧情况。

代码实现
代码的主体部分是锅炉矢量图,锅炉火焰的数据绑定以及用 Animation 插件实现炉内火焰的动画。首先要生成数据容器和拓扑组件并将其添加到 body 中 。
dataModel = new ht.DataModel(); graphView = new ht.graph.GraphView(dataModel); view = graphView.getView(); document.body.appendChild(view);
首先我们先来生成底部的动态火焰效果,第一步我们先注册图片信息:
var image = []; // 这里加入图片的文件名
for(var i = 0; i < image.length; ++i) {
ht.Default.setImage('fireNum' + i, image[i]); // 这里图片和 html 在同一路径下,如不在同一路径 ,加上前缀路径名
}
然后要实现静态火焰图片的动态效果,无非就是将图片连续循环播放,于是需要动态改变的就是图片的文件名了,于是火焰图片的数据绑定如下:(将这段代码加入到锅炉外观的注册代码中)
{
type: 'image',
name: {
func: function(data) {return data.a('imgNum');} // 绑定了一个方法,用以动态改变图片的 name 属性值
},
rect: [50, 325, 450, 280] // 设置火焰图片的位置和大小
}
要用 Animation 实现实现动画效果首先必须引入 ht-animation.js 文件:
<script src = "lib/ht-animation.js"></script>
然后数据模型调用 enableAnimation(interval) 启动动画定时器,让节点实现 Animation
dataModel.enableAnimation();
node.setAnimation({
flash: { // 自定义的任意方法名
from: 0, // 表示参数的开始值,从 0 开始
to: image.length - 1, // 到 image.length - 1 结束
onUpdate: function(value) { // 回调函数,动画的每一帧都会回调此函数。
this.a('imgNum', 'fireNum' + value); // 改变图片的文件名
},
frames: 69, // 动画的帧数,等于参数变化范围 - 1 (获得的参数刚好是整数),使得每一张图片都会被显示
easing: 'Linear', // 动画的方式,这里采用线性改变(保证参数刚好是整数)
repeat: true // 上述过程是否重复
},
start: ["flash"] // 指定要启动的动画,里只定义了一个名为 flash 的动画,事实上,你可以定义任意多个
});
接下来我们把美工提供的锅炉外观信息注册成图片 fire ,并将火焰图片信息注册进锅炉外观
ht.Default.setImage('fire', {
"width": 543,
"height": 639,
"comps": [
{
"type": "shape",
"background": "#7f7f7f",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
17.90813,
17.93993,
17.90813,
319.18021,
141.34629,
415.11661,
141.34629,
620.42049,
401.01413,
620.42049,
401.01413,
415.11661,
525.09187,
319.18021,
525.09187,
17.93993,
17.90813,
17.93993,
17.90813,
17.93993
]
},
{
"type": "shape",
"background": "#999999",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
58.20141,
17.93993,
58.20141,
319.18021,
161.81272,
415.11661,
161.81272,
620.42049,
379.90813,
620.42049,
379.90813,
415.11661,
483.51943,
319.18021,
483.51943,
17.93993,
58.20141,
17.93993,
58.20141,
17.93993
]
},
{
"type": "shape",
"background": "#b2b2b2",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
127.91519,
17.93993,
127.91519,
319.18021,
197.62898,
415.11661,
197.62898,
620.42049,
346.0106,
620.42049,
346.0106,
415.11661,
415.72438,
319.18021,
415.72438,
17.93993,
127.91519,
17.93993,
127.91519,
17.93993
]
},
{
"type": "shape",
"background": "#cccccc",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
209.78092,
17.93993,
209.78092,
319.18021,
241.12014,
415.11661,
241.12014,
620.42049,
304.43816,
620.42049,
304.43816,
415.11661,
333.85866,
319.18021,
333.85866,
17.93993,
209.78092,
17.93993,
209.78092,
17.93993
]
},
{
"type": "shape",
"borderWidth": 1.27915,
"borderColor": "#000000",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
17.90813,
17.93993,
17.90813,
319.18021,
141.34629,
415.11661,
141.34629,
620.42049,
401.01413,
620.42049,
401.01413,
415.11661,
525.09187,
319.18021,
525.09187,
17.93993,
17.90813,
17.93993
]
},
{
"type": "shape",
"borderWidth": 1.27915,
"borderColor": "#7f7f7f",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
141.98587,
223.24382,
401.65371,
223.24382
]
},
{
"type": "shape",
"borderWidth": 1.27915,
"borderColor": "#7f7f7f",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
17.90813,
319.18021,
525.09187,
319.18021
]
},
{
"type": "shape",
"borderWidth": 1.27915,
"borderColor": "#7f7f7f",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
264.14488,
291.67845,
264.14488,
223.24382
]
},
{
"type": "shape",
"background": "#336666",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
31.9788,
606.9894,
511.66078,
606.9894,
511.66078,
333.25088,
31.9788,
333.25088,
31.9788,
606.9894,
31.9788,
606.9894
]
},
{
"type": "shape",
"borderWidth": 1.27915,
"borderColor": "#000000",
"shadowColor": "#1ABC9C",
"rotation": 3.14159,
"points": [
31.9788,
606.9894,
511.66078,
606.9894,
511.66078,
333.25088,
31.9788,
333.25088,
31.9788,
606.9894,
31.9788,
606.9894
]
},
{
type: 'image',
name: {
func: function(data) {return data.a('imgNum');} // 绑定了一个方法,用以动态改变图片的 name 属性值
},
rect: [50,325,450,280] // 设置火焰图片的位置和大小
}
});
而后要创建一个节点将图片 fire 添加进节点,并将节点添加进数据容器:
node = new ht.Node();
node.setImage('fire');
node.a({
'imgNum': 'fireNum0'
});
node.setPosition(200, 200);
dataModel.add(node);
至此,模拟锅炉燃烧的模式就全部搭建完成,主体部分实际上是锅炉矢量图,锅炉火焰图的数据绑定以及用 Animation 插件实现炉内火焰的动画。
总结:这个 Demo 主要就是用 Animation 插件实现动画效果,其中 Animation 中有很多的参数,这里我们没有指定 property 和 accessType,因为图片名参数 imgNum 不是单纯的数字类型, 所以我们就用 onUpdate 回调函数,在动画的每一帧都动态的改变 imgNum 的值,使得其不断更换图片从而在视觉上造成一种动画的效果。

浙公网安备 33010602011771号