前言
近年来,随着前端技术的迅速发展,H5游戏也开始得到普及,那么什么是H5游戏呢?它的本质其实就是一组组可以控制的动画,那么动画又要怎样去实现呢?是通过css3?还是说直接用js来操作dom节点?我们知道,频繁地操作dom节点会触发浏览器的重绘和回流,过多的重绘和回流会降低页面的性能,从而就会影响到用户的体验,那么应该要使用什么来实现动画呢?答案就是canvas。
内容
canvas动画的实现
我们对于canvas的认识就只是知道它是用来绘制图形、图片等等,这些都是静态的并不会动,那么要如何使用canvas来做动画呢?这里首先要说一下动画是怎样形成的,动画的形成是基于“视觉暂留”的原理,所谓的“视觉暂留”指的就是人的眼睛在看到一个画面后,在0.34秒内这个画面是不会消失的,如果在前一个画面还没有消失前就出现下一个画面,这样就会给人造成一种流畅的视觉变化效果,也就形成了动画。这样我们就可以先用canvas绘制出一个画面,然后在0.34秒内将canvas清掉再绘制下一个画面,如此循环,就实现了canvas的动画效果。
lufylegend的基本实现原理
canvas动画的实现可以总结如下图:
1、首先是用ctx.clearRect()清除掉上一次绘制的画面。
2、计算两次绘制之间的时间间隔,为什么要计算这个时间间隔呢?因为一个合理的动画,其每一次循环所要移动的距离都是要基于时间的,也就是位移量=速度*时间。
3、遍历绘图对象数组,计算出每一个绘图对象在这一次循环中的最后位置,然后调用其绘制的方法将其绘制到canvas上,这里的绘图对象是通过事先创建好的绘图对象构造函数来创建的,之所以要创建一个绘图对象的构造函数,是因为这些绘图对象都有一些相同的属性和方法,用构造函数的方式会更便于管理这些属性和方法。
由此可见,要做一个canvas动画,既要关注绘制的逻辑,又要关注运动的逻辑,而且随着动画复杂程度的增加,这些逻辑就会越来越复杂,一不小心就很容易搞混出错,出错后的debug也会异常的困难。因此,lufylegend就是为了解决这种问题而产生的。
Lufylegend其实就是将上面讲到的动画的循环过程、绘图对象的构造以及绘制的逻辑都封装起来,因此通过使用lufylegend,我们只需要关注每一个绘图对象是如何运动以及多个绘图对象之间的交互逻辑就可以了,这样就大大降低了出错率以及缩小了出错后的debug范围,让我们把更多的精力放在动画效果的实现逻辑上。
lufylegend的简单应用
那么要如何去使用lufylegend来实现动画呢?这里首先要介绍几个核心的类。
LInit
严格来说LInit并不是lufylegend里面的一个类,它其实是一个方法,主要是用来创建canvas画布以及开始动画的轮询。
用法:
LInit(requestAnimationFrame,'canvasBox',500,500,function(){});
第一个参数可以传轮询函数或轮询的时间间隔,如果传的是轮询的时间间隔则使用的是setInterval,这里我建议用requestAnimationFrame,它是一个专门制作动画的函数,是由浏览器来控制帧速率的,不过在使用之前要进行封装一下。第二个参数传的是canvas的容器节点的id,第三第四个参数分别是canvas的宽和高,第五个参数是生成canvas节点后的回调函数。至此就生成了一个已经在不断绘制的canvas节点,这时有人可能会问,不是已经在绘制了吗?为什么页面上什么都没有?是不是没有初始化成功?前文已经提到过,在动画一次循环的最后是要遍历绘图对象数组把每一个绘图对象绘制出来的,而初始化canvas的时候这个绘图对象数组里面根本就没有东西,所以哪来的图像呢?
LBitmapData
LBitmapData是创建LBitmap这个类的实例所需要的参数对象。
用法:
var bitmapData = new LBitmapData('#4381fd',0,0,100,100);
第一个参数可以传image对象或十六进制颜色,如果传的是image对象则绘制出来的是一张图片,如果传的是十六进制颜色则绘制出来的是一个该颜色的填充矩形,第二第三个参数传的是图片或矩形在画布中左上角的x坐标和y坐标,第四第五个参数传的是显示的宽和高。
LBitmap
LBitmap是lufylegend用于显示位图图像的一个类,它只能接收LBitmapData所创建的实例作为参数。
用法:
var bitmapData = new LBitmapData('#4381fd',0,0,100,100);
var bitmap = new LBitmap(bitmapData);
LSprite
LSprite是lufylegend的一个基本显示列表构造类,它的实例是一个可以显示图形并且也可以包含子项的显示列表节点,也就是说,只有放到LSprite实例上的LBitmap实例才能显示在canvas上。
用法:
var bitmapData = new LBitmapData('#4381fd',0,0,100,100);
var bitmap = new LBitmap(bitmapData);
var sprite = new LSprite();
sprite.addChild(bitmap);
addChild(sprite);
LTweenLite
LTweenLite是lufylegend一个比较常用的动画类,其包含了各种缓动效果。
用法:
var bitmapData = new LBitmapData('#4381fd',0,0,100,100);
var bitmap = new LBitmap(bitmapData);
LTweenLite.to(bitmap,0.3,{
x: 100,
y: 100,
delay: 2,
loop: true,
onComplete: function(e){}
});
第一个参数传的是要进行缓动的对象,可以是LSprite或LBitmap的实例,第二个参数传的是缓动持续的时间,第三个参数传的是要缓动的对象的所有属性,可以是xy坐标、宽高、透明度等等,只要是该对象有的属性都能进行缓动,除了对象属性以外还可以配置一些特殊值,比如配置了delay: 2缓动就会延迟2秒后才开始,配置了loop: true缓动就会持续循环,配置了onComplete: function(e){}缓动结束时就会触发这个方法,其中e是当前进行缓动的对象,这里只列举几个比较常用的特殊值。
小结
市面上除了lufylegend以外还有其他的H5游戏引擎,比如egret、laya、cocos-js等等,相比于这些H5游戏引擎,lufylegend的优势在于它比较轻量级,而且源码看起来也不是特别的复杂,比较容易能看得懂,对于实现一些2d类的游戏动画来说,用lufylegend就已经足够了。
最后附上api文档链接http://lufylegend.com/api/zh_CN/out/index.html
这是把沉淀在其他平台的文章 都找出来了么。一下发了这么多
凡科有几百号的开发人员,这段时间产出的文章比较多,大部分的开发都集中发了。
66666
小程序可以使用吗?
对于动画的每一帧的绘制, 你们是只重绘变动区域, 还是整个canvas都重绘?
小程序的canvas接口微信修改过了,应该要对框架做一写修改去适应,不过具体没试过在小程序里面用过。这个是整个canvas重绘,只重绘变动区域会导致逻辑变得很复杂,特别是有多个层级重叠的时候
小程序 canvas 好像不支持requestAnimationFrame, 只有WebGL才支持,你们有直接可以把2D的动画通过WebGL 来绘制的吗?