Canvas是HTML5新增的组件,它就像一块幕布,可以用JavaScript在上面绘制各种图表、动画等。
没有Canvas的年代,绘图只能借助Flash插件实现,页面不得不用JavaScript和Flash进行交互。有了Canvas,我们就再也不需要Flash了,直接使用JavaScript完成绘制。
经常玩抖音、火山小视频的朋友都会发现在礼物按钮旁边经常会出现一些动画效果,本篇博客波波将以示例分享点赞小爱心的制作过程。先看演示效果:
实现原理:
1.动画中每颗心都有自己的透明度,位移,角度,缩放的变化动画,针对这些动画,可以分别调用canvas的相关API:
- ctx.translate(this.x, this.y);
- ctx.rotate(this.angle);
- ctx.scale(this.scale, this.scale);
- ctx.globalAlpha = this.opacity;
2、在有大于1颗心的情况时,针对每颗心,在实现角度,缩放时必须要保存上一次canvas的状态,改变完成之后在恢复:
- ctx.save();
- ctx.translate(this.x, this.y);
- ctx.rotate(this.angle);
- ctx.scale(this.scale, this.scale);
- ctx.globalAlpha = this.opacity;
- ctx.restore();
3.计算心位移路径(3次被塞尔曲线):
转换成js代码计算心的x,y方向上的位移:
- /**
- * 获得贝塞尔曲线路径
- * 一共4个点
- */
- function getBezierLine(heart){
- var obj = heart.bezierPoint;
- var p0 = obj.p0;
- var p1 = obj.p1;
- var p2 = obj.p2;
- var p3 = obj.p3;
- var t = heart.bezierDis;
- var cx = 3 * (p1.x - p0.x),
- bx = 3 * (p2.x - p1.x) - cx,
- ax = p3.x - p0.x - cx - bx,
- cy = 3 * (p1.y - p0.y),
- by = 3 * (p2.y - p1.y) - cy,
- ay = p3.y - p0.y - cy - by,
- xt = ax * (t * t * t) + bx * (t * t) + cx * t + p0.x,
- yt = ay * (t * t * t) + by * (t * t) + cy * t + p0.y;
- heart.bezierDis += heart.speed;
- return {
- xt: xt,
- yt: yt
- }
- }
路径如图所示:
根据曲线路径方法可以实现心的运动轨迹:
4.针对每一帧需要动态修改,心的位移,角度,和缩放:
- /**
- * 计算缩放角度的方法
- */
- function getFScale(heart){
- let _scale = heart.scale;
- // 随着距离起始点的距离增加,scale不断变大
- let dis = heart.orignY - heart.y;
- _scale = (dis / heart.scaleDis);
- // 当大于设置的阈值时变成1
- if (dis >= heart.scaleDis) {
- _scale = 1;
- }
- return _scale;
- }
5.计算心角度变化:
- /**
- * 计算心左右摇摆的方法
- */
- function rangeAngle(heart) {
- let _angle = heart.angle;
- // 心介于[start, end]之间不断变化角度
- if(_angle >= heart.angelEnd) {
- // 角度不断变小,向左摇摆
- heart.angleLeft = false;
- } else if (_angle <= heart.angelBegin){
- // 角度不断变大,向又摇摆
- heart.angleLeft = true;
- }
- // 动态改变角度
- if (heart.angleLeft) {
- _angle = _angle + 1;
- } else {
- _angle = _angle - 1;
- }
- return _angle;
- }
组件化:
整个组件代码不超过200行,相较于使用css3实现更加轻便,dom少,性能更好。
组件地址:https://github.com/lvming6816077/like-heart