在上文,我们创建了图形后,可以使用obj.set()方法变更图形对象的属性。
那么要实现动画效果,肯定要类似地定义好动画的起始状态,这样才能转化成一帧帧动画。
当我们在画布上渲染出一个图案的时候,就相当于已经创建了初始的那一帧。那么要能计算出动画,则需要再定义下变化的属性(也就是定义出结束的状态。)
为了简洁起见,创建的图案对象我都使用obj代替。
fabric提供了这种动画的设置api:
obj.animate(
"要设置的属性名",
要设置的属性值,
{
//动画参数的设置
onChange:canvas.renderAll.bind(canvas)
}
)
一,指定绝对属性
举个例子,让我的文本对象旋转到指定角度的动画。
const canvas = new fabric.Canvas("canvas");
canvas.setBackgroundColor("rgb(100,200,200)");
const txt = new fabric.Text('test', {
left: 140, // 位置
top: 140,
shadow: 'rgba(0,0,0,0.3) 15px 15px 15px', // 阴影
fontFamily: 'Hoefler Text', // 字体
stroke: '#ff1318', // 画笔颜色
strokeWidth: 2, // 画笔粗度
fill: '#0f0', //填充颜色
fontSize: 60, // 字体大小
});
txt.animate(
"angle",
135,
{
onChange:canvas.renderAll.bind(canvas),
duration:3000
}
)
canvas.add(txt);
实现的效果:
二,指定相对属性
animate
的一个便利功能是它还支持相对值,例如我只想相对当前宽度增加100:
const canvas = new fabric.Canvas("canvas");
canvas.setBackgroundColor("rgb(100,200,200)");
const rect = new fabric.Rect({
left: 100,
top: 100,
width: 30,
height: 30,
fill: "yellow",
});
rect.animate(
"width",
'+=100',
{
onChange:canvas.renderAll.bind(canvas),
duration:3000
}
)
canvas.add(rect);
实现的效果:
三,动画参数的说明
上文说过,第三个对象参数,里面是设置动画的一些参数,它是可选的。但是注意到,每次都用了onChange方法。为什么呢?
因为当我们调用animate
方法时,它只会按照特定算法(即缓动)随时间对属性值进行动画处理。但在每次更改角度后都不会重新渲染画布屏幕。我们显然需要重新渲染才能看到实际的动画。所以这里手动告诉它,每次属性变更后,这个对象重新渲染,于是我们才能看到动画。
这个动画参数可以传的属性有如下几个
from:允许指定可设置动画的属性的起始值(如果我们不希望使用当前值)。
onChange:canvas.renderAll.bind(canvas),属性值变更,重新渲染画布
duration:默认为500(ms)。可用于更改动画的持续时间。
onComplete:在动画结束时调用的回调。
easing:缓动功能。具体值查看:http://fabricjs.com/docs/fabric.util.ease.html
示例:
const canvas = new fabric.Canvas("canvas");
canvas.setBackgroundColor("rgb(100,200,200)");
const rect = new fabric.Rect({
left: 100,
top: 100,
width: 30,
height: 30,
fill: "yellow",
});
rect.animate(
"width",
'+=100',
{
from:50,
onChange:canvas.renderAll.bind(canvas),
duration:2000,
easing: fabric.util.ease.easeOutBounce,
}
)
canvas.add(rect);
实现的效果:
四,旋转时让绕中心旋转
默认情况下,图案对象的原点是在左上角,所以直接设置旋转动画,是绕着左上角进行旋转的。
为了让它绕中心旋转,可以设置对象的基准点为中心位置:
const canvas = new fabric.Canvas("canvas");
canvas.setBackgroundColor("rgb(100,200,200)");
const rect = new fabric.Rect({
left: 50,
top: 50,
width: 50,
height: 50,
fill: "yellow",
originX: 'center',//调整中心点的X轴坐标
originY: 'center'//调整中心点的Y轴坐标
});
// 旋转动画
rect.animate('angle', rect.left === 50 ? 360 : 50, {
duration: 1000,
onChange: canvas.renderAll.bind(canvas),
easing: fabric.util.ease.easeInCubic
});
canvas.add(rect);
实现的效果:
可以注意到的是:虽然旋转中心换到中间了,但是left,top的基准也变成这个中心了(之前也是默认的左上角)。
五,同时多个动画效果并循环播放
当我们想要多个动画效果同时触发时:
const canvas = new fabric.Canvas("canvas");
canvas.setBackgroundColor("rgb(100,200,200)");
const rect = new fabric.Rect({
left: 50,
top: 50,
width: 50,
height: 50,
fill: "yellow",
originX: 'center',//调整中心点的X轴坐标
originY: 'center'//调整中心点的Y轴坐标
});
// 动画效果
function animate() {
// 移动动画
rect.animate('left', rect.left === 50 ? 275 : 50, {
duration: 1000,
onChange: canvas.renderAll.bind(canvas),
onComplete: animate
});
// 旋转动画
rect.animate('angle', rect.left === 50 ? 360 : 0, {
duration: 1000,
onChange: canvas.renderAll.bind(canvas),
});
// 放大动画
rect.animate('width', rect.left === 50 ? 100 : 50, {
duration: 1000,
onChange: canvas.renderAll.bind(canvas),
});
}
animate()
canvas.add(rect);
实现的效果: