模仿实现一个直播的点赞动画
2020/5/10 11:26:44
本文主要是介绍模仿实现一个直播的点赞动画,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
在阅读了H5 直播的疯狂点赞动画是如何实现的?(附完整源码)这篇文章后感觉这个点赞效果很不错,并且也跟着作者实现了一下这个动画效果。其中css的实现方式很容易理解,但是我在读完作者canvas实现方法之后有不同的实现思路,因此又按照自己的思路实现了一下。实现效果如下:
实现思路
我看到这个动画效果首先想到的,声明一个包含多个小图标对象的数组,通过在不同的位置绘制这些小图标实现这个点赞动画。那么首先我们实现一个小图标的动画。
动画流程分解
要做动画我们首先把整个动画流程分解一下,这个动画包含如下几个:
- 放大
图片刚出现时有一个放大动画 - y轴平移
- x轴平移
即图标左右摆动的动画 - 透明度
图标消失时的透明度动画
单个图标动画
我们这里首先将问题先简单化处理,制作单个图标的动画。这里为了之后对图标动画的操作,我写了一个Ani类表示图标动画,它包含了图标的位置属性、大小、image
对象和动画轨迹相关的属性,还有一个用来绘制的draw
方法。定义如下:
//图标动画类 class Ani{ constructor(img,x,y,w,h){ this.x=x; this.y=y; this.width=w; this.height=h; this.image=img; //随机生成正弦曲线的波动幅度 this.step=getRandom(10,60); //随机生成y轴的移动速度 this.spite=getRandom(2,6); //正弦函数的摆动频率 this.frequency=getRandom(50,100); //小图标透明度 this.op=0; //随机曲线类型 Math.random()>=0.5?this.type=1:this.type=2; //y轴偏移量,作为正弦函数的参数 this.dy=0; } //这里不用全局的context是为了方便复用 draw(context){ //y轴平移动画 this.y-=this.spite; //x轴摆动动画 this.dy+=this.spite; let dx=0; //不同的波动方向 this.type==1?dx=Math.sin(this.dy/this.frequency):dx=Math.sin(-this.dy/this.frequency); let x=this.x+dx*this.step; //放大动画 if(this.width<50){ this.width+=0.5; this.height+=0.5; } context.drawImage(this.image,x,this.y,this.width,this.height); //消失时的透明度动画 if(this.y<50){ this.op+=0.05 context.fillStyle = `rgba(255,255,255,${this.op})`; context.fillRect(x,this.y,this.width,this.height); } } } 复制代码
稍微解释一下上面的代码,构造函数中的frequency
属性是用来控制正弦函数的摆动频率的,大家可以修改它的值来查看效果,getRandom()
方法是用来获得某个区间之间的随机数的一个简单函数,下面的完整源码中给出了代码实现。
这里设置图标的透明度是通过在指定位置添加透明背景色实现的,在网上查了好多也没又找到直接修改image对象透明度的方法,因此使用了这个方法。
Ani
类draw()
方法通过改变Ani对象的y
、x
、width
、height
、op
等属性分别实现各个动画过程。这里着重说一下x
轴的摆动动画的实现,x
轴的运动动画是借助正弦函数实现的,js
有现成Math.sin()
函数供我们使用,正弦函数的0->1->0->-1
的曲线完美符合我们需要的运动曲线。这里我们把y
轴偏移量dy
作为正弦函数的参数,生成0~-1
之间的值dx
,再使用dx*step
获得x
轴的偏移量。
Ani
类完成之后我们还需要一个启动动画的函数:
const canvas = document.getElementById('thumsCanvas'); let context = canvas.getContext('2d'); let image=new Image("./img/star.png"); let ani=new Ani(image,250/2-50/2,500-50,20,20); //渲染函数 function render(){ //context.clearRect(0,0,250,500); // clear canvas //添加透明背景色填充,实现拖尾效果 context.fillStyle = 'rgba(255,255,255,0.5)'; context.fillRect(0,0,250,500); ani.draw(context); window.requestAnimationFrame(render) } render(); 复制代码
多个图标动画
实现了单个图标的动画,那么多个图标的动画就很容易实现了。我们只需要创建一个数组持有多个图标对象,在每次render函数执行时遍历绘制它们。
因为我们需要多个图像的图标对象,因此我们需要实现一个loadImge函数把要加载的图像先缓存到一个imageList数组中,此方法参考上面的文章H5 直播的疯狂点赞动画是如何实现的?(附完整源码)。 代码如下:
//加载图像 function loadImage(){ const images=[ '../img/red.png', '../img/dog.png', '../img/cat.png', '../img/star.png', '../img/zan.png', ]; const promiseList=[]; images.forEach(element => { let p=new Promise((resolve)=>{ const img=new Image(); img.onload=resolve.bind(null,img) img.src=element; }) promiseList.push(p) }); return new Promise(resolve=>{ Promise.all(promiseList).then(imgs=>{ this.imageList=imgs; resolve(); }) }) } 复制代码
然后我们需要把一个方法添加图标对象:
//添加图标对象到数组 function tapAdd(){ let image=this.imageList[this.getRandom(0,5)]; let ani=new Ani(image,250/2-50/2,500-50,20,20) aniList.push(ani) } 复制代码
最后我们同样需要一个渲染函数:
//渲染函数 function render(){ //context.clearRect(0,0,250,500); // clear canvas context.fillStyle = 'rgba(255,255,255,0.5)'; context.fillRect(0,0,250,500); aniList.forEach((ani,index)=>{ if(ani.y<-50){ ani=null; }else{ ani.draw(context); } }) window.requestAnimationFrame(render) } loadImage().then(()=>{ console.log('图像加载完成') render(); setInterval(tapAdd,100); }); 复制代码
这里两句context.fillStyle = 'rgba(255,255,255,0.5)';context.fillRect(0,0,250,500);
是通过添加半透明填充色实现拖尾效果,如果不需要可以直接换成context.clearRect(0,0,250,500);
。
完整源码
<!DOCTYPE html> <html> <head> <title>cavans点赞动画效果</title> </head> <body> <canvas onclick="tapAdd()" id="thumsCanvas" width="250" height="500" style="width:250px;height:500px;background-color: #f4f4f4;"></canvas> </body> <script> //图标动画类 class Ani{ constructor(img,x,y,w,h){ this.x=x; this.y=y; this.width=w; this.height=h; this.image=img; //随机生成正弦曲线的波动幅度 this.step=getRandom(10,60); //随机生成y轴的移动速度 this.spite=getRandom(2,6); this.frequency=getRandom(50,100); //小图标透明度 this.op=0; //随机曲线类型 Math.random()>=0.5?this.type=1:this.type=2; this.dy=0; } draw(context){ //y轴动画效果 this.y-=this.spite; //x轴动画效果 this.dy+=this.spite; let dx=0; //不同的波动方向 this.type==1?dx=Math.sin(this.dy/this.frequency):dx=Math.sin(-this.dy/this.frequency); let x=this.x+dx*this.step; //图像放大动画 if(this.width<50){ this.width+=0.5; this.height+=0.5; } context.drawImage(this.image,x,this.y,this.width,this.height); //图像消失动画,透明度从0-1 if(this.y<50){ this.op+=0.05 context.fillStyle = `rgba(255,255,255,${this.op})`; context.fillRect(x,this.y,this.width,this.height); } } } //小图标动画对象数组 let aniList=[]; const canvas = document.getElementById('thumsCanvas'); let imageList=[]; let context = canvas.getContext('2d'); //加载图像 function loadImage(){ const images=[ '../img/red.png', '../img/dog.png', '../img/cat.png', '../img/start.png', '../img/zan1.png', ]; const promiseList=[]; images.forEach(element => { let p=new Promise((resolve)=>{ const img=new Image(); img.onload=resolve.bind(null,img) img.src=element; }) promiseList.push(p) }); return new Promise(resolve=>{ Promise.all(promiseList).then(imgs=>{ this.imageList=imgs; resolve(); }) }) } //获取随机数 function getRandom(min,max){ return Math.floor(Math.random()*(max-min))+min } //添加图标 function tapAdd(){ let image=this.imageList[this.getRandom(0,5)]; let ani=new Ani(image,250/2-50/2,500-50,20,20) aniList.push(ani) } //渲染函数 function render(){ //context.clearRect(0,0,250,500); // clear canvas context.fillStyle = 'rgba(255,255,255,0.5)'; context.fillRect(0,0,250,500); aniList.forEach((ani,index)=>{ if(ani.y<-50){ ani=null; }else{ ani.draw(context); } }) window.requestAnimationFrame(render) } loadImage().then(()=>{ console.log('图像加载完成') render(); setInterval(tapAdd,100); }); </script> </html> 复制代码
图片素材
zan.png
cat.png dog.png heart.png star.png最后
以上就是自己在阅读了H5 直播的疯狂点赞动画是如何实现的?(附完整源码)之后按照自己的思路实现的一个直播点赞效果,对作者表示感谢。
如果有好的修改建议欢迎大家提出,感觉还可以的话,欢迎点赞~这篇关于模仿实现一个直播的点赞动画的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-24怎么修改Kafka的JVM参数?-icode9专业技术文章分享
- 2024-12-23线下车企门店如何实现线上线下融合?
- 2024-12-23鸿蒙Next ArkTS编程规范总结
- 2024-12-23物流团队冬至高效运转,哪款办公软件可助力风险评估?
- 2024-12-23优化库存,提升效率:医药企业如何借助看板软件实现仓库智能化
- 2024-12-23项目管理零负担!轻量化看板工具如何助力团队协作
- 2024-12-23电商活动复盘,为何是团队成长的核心环节?
- 2024-12-23鸿蒙Next ArkTS高性能编程实战
- 2024-12-23数据驱动:电商复盘从基础到进阶!
- 2024-12-23从数据到客户:跨境电商如何通过销售跟踪工具提升营销精准度?