动画相关
制作动画的基本步骤
-
清理画布:ctx.clearRect(0,0,canvas.width,canvas.height)
-
保存 canvas 上下文对象的状态:ctx.save()
-
绘制动画图形:…
-
恢复 canvas 上下文对象的状态:ctx.restore()
驱动动画的方法
- setTimeOut(fn,time) 和setInterval(fn,time)
优点:使用方便,动画的时间间隔可以自定义。
缺点:隐藏浏览器标签后,会依旧运行,造成资源浪费。与浏览器刷新频率不同步。 - requestAnimationFrame(fn)
优点:性能更优良。隐藏浏览器标签后,便不会运行。与浏览器刷新频率同步。
缺点:动画的时间间隔无法自定义
速度和加速度
-
速度:描述物体运动快慢和运动方向的物理量
-
加速度:描述速度变化的量
匀速运动
obj.x+=vx;
obj.y+=vy;
加速运动:
vx += ax;
vy += ay;
obj.x+=vx;
obj.y+=vy;
请求动画帧里的时间差
请求动画帧里的时间差是参差不齐的。比如第一次用16 毫秒驱动了动画,下一次可能是20毫秒,下下次可能是17 毫秒。
常见的误区:
比如:超人第一秒跑了100 米,第二秒内也跑了一百米,第三秒内跑了一百米,但是这并不是真正的匀速运动,虽然这样算出来的平均速率是100M/s。
但是定义匀速运动与否的单位是平均速度(区别与匀速率)正确的匀速运动应该是超人一直以100M/s的速度运动,第一秒跑了一百米,第二秒跑了一百米 。。。。。。
弹性运动
从小球落地的事件中解析弹性运动
初始数据
速度:vy=0
加速度(重力):ay=0.01
弹力:bounce=0.8
动画帧中:
vy+=ay
ball.y+=vy
碰撞地面时:
vy*=-bounce
vx*=-bounce
补间动画
补间动画是在两个关键帧之间,以某种算法自动计算物体运动的插值,从而形成一种过度效果。
用tween.js 做补间
颜色补间动画
tween.js 并没有提供颜色的过度方法,所以我把d3 的color 插件拼装到了tween.js 中去,形成了一个SupTween.js,使用之前需要引入
用户交互
添加交互
canvas 图形没有监听事件的方法。
比如用鼠标选择图形时,我们只能用canvas 画布监听事件,获取鼠标或触摸点在canvas 中的位置,再基于图形在canvas 中的位置和形状,判断鼠标在canvas中的点位是否在图形中。
获取canvas 中鼠标位置的方法
canvas.addEventListener('mousedown', getPos);
function getPos(event){
const {clientX,clientY}=event;
const {left,top}=canvas.getBoundingClientRect();
const [x,y]=[clientX-left,clientY-top];
console.log(x,y);
}
扩展-获取触摸点点位的方法
canvas.addEventListener('mousedown', getPos);
function getPos(event){
const {pageX, pageY}=event.changedTouches[0];
const {left,top}=canvas.getBoundingClientRect();
const [x,y]=[pageX -left, pageY -top];
console.log(x,y);
}
isPointInPath(x,y) 选择图形
isPointInPath(x,y) 是canvas 2d中的内置方法,它可以判断一个点位是否在路径中。
isPointInPath(x,y) 面向的对象是路径,所以对文字、fillRect()、strokeRect()不好使。
回顾一下路径的基本概念:在我们使用canvas 的getContext(‘2d’) 方法获取canvas 上下文对象ctx 的时候, ctx上便挂载了一个空的路径集合。在ctx.beginPath() 之后,所绘制的所有路径都会被添加到这个路径集合里,isPointInPath(x,y) 方法判断的就是x、y 点是否在这个路径集合的所有路径里。这个路径可以不用画出来,只要路径集合里有路径即可。注意,在下一次ctx.beginPath() 时,路径集合会被置空。
示例:用三个点画了一条折线,没有将其闭合,然后对其进行选择。
const ctx=canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(450,50);
ctx.lineTo(250,200);
console.log(ctx.isPointInPath(250,100)); //true
ctx.stroke();
总结:
动画是像素在时间中的舞蹈。无论多么炫酷的动画,它都是在改变屏幕中像素的位置和色彩。
动画可以应用于canvas 图形的位置、旋转、缩放和样式。
动画的制作方式有两种:逐帧动画和补间动画。
逐帧动画只会考虑下一帧。
补间动画在动画的开始就已经知道了动画的结尾,只是动画的过程会有各自的精彩。