当前位置: 首页 > Web前端 > HTML5

腾讯课堂H5直播间动画实现一(CSS)

时间:2023-04-05 20:53:55 HTML5

1.前言以前看微信视频号直播的时候,经常点右下角的赞。看着它的数字从一位数慢慢变成五位数,颇有气氛。尤其是长按的时候,还有手机的震动反馈,非常有感触。虽然我很好奇这些飘动似的运动效果是如何实现的,但并没有特别去研究。直到前段时间投入到腾讯课堂H5直播间的需求中,需要自己实现这样的效果,才开始摸索。先来看看最终效果:相比视频号的like运动效果,轨迹要复杂很多。可以看到,课堂直播间的点赞动画大致分为三个阶段:1.从头开始,在上升过程中放大到正常大小2.在上升过程中左右摇摆,并且摇摆幅度是随机的3.在上下摇摆的过程中,在做之前先淡出收缩,我首先想到的是用CSS动画来实现这种运动轨迹。完成后用Canvas重构了一个版本来优化性能。接下来,我们分别来看一下这两种实现方式。2.CSS实现like运动效果2.1轨迹分析由于like动画是在二维平面上,我们可以将它的运动轨迹分成x轴和y轴两段。在y轴上很简单,我们的点赞图标会做一个匀速垂直向上的运动,从容器底部上升到容器顶部。x轴左右摇摆。从数学的角度来看,它是一种简谐运动。但是用css实现的话,就不需要那么精细了。为了简化计算,我们可以使用几个关键帧来串联这个运动轨迹,例如:@keyframesbubble_swing{0%{Middle}25%{Leftmost}75%{Rightmost}100%{Middle}}2.2轨迹设计根据针对以上分析,我们可以设计一段相同的上升轨迹,和几段不同的左右摇摆轨迹。上升轨迹很简单,我们还可以添加不透明度和变换变化,如下:@keyframesbubble_y{0%{transform:scale(1);保证金底部:0;不透明度:0;}5%{变换:缩放(1.5);不透明度:1;}80%{变换:比例(1);不透明度:1;}100%{底部边距:var(--cntHeight);变换:比例(0.8);不透明度:0;}}其中--cntHeight指的是容器的高度。也就是说,我们通过不断增加margin-bottom来控制点赞图标从容器底部上升到容器顶部。对于横向运动的轨迹,为了增加运动轨迹的多样性,我们可以设计多个摇摆轨迹,例如“中间->最左->中间->最右”的轨迹:@keyframesbubble_swing_1{0%{//中间margin-left:0;}25%{//最左边margin-left:-12px;}75%{//最右边margin-left:12px;}100%{左边距:0;}}这里也用margin来控制图标的左右移动。同样,我们也可以设计其他几个轨道://Anytrack@keyframesbubble_swing_2{0%{//Middlemargin-left:0;}33%{//最左边的margin-left:-12px;}100%{//随机位置margin-left:6px;}}//谐波反转@keyframesbubble_swing_3{0%{//middlemargin-left:0;}25%{//最右边margin-left:12px;}75%{//最左边margin-left:-12px;}100%{左边距:0;}}接下来我们结合x轴和y轴轨迹(@keyframes)并设置随机动画时间,例如:@for$ifrom1through3{@for$jfrom1through2{.bl_#{$i}_#{$j}{animation:bubble_ycalc(1.5s+$j*0.5s)linear1forwards,bubble_swing_#{$i}calc(1.5s+$j*0.5s)linear1forwards;}}}这里生成了3*2=6个不同的轨迹。对于这种重复的选择器,在SCSS中使用循环语法可以节省大量代码。2.3随机选择图片(Sprite图片)每次我们喜欢都会出现不同的icon,所以这里我们针对不同的icon设计了一系列的selector,让它们显示不同的图片。首先我们需要准备一张sprite图片,让所有的图标大小保持一致,然后使用SCSS循环语法:@for$ifrom0through7{.b#{$i}{background:url('../../images/like_sprites.png')计算(#{$i}*-24px)0;}}如上生成了8个选择器,我们可以在程序执行的时候随机给图标分配一个选择器。2.4生成点赞图标的CSS部分已经差不多完成了,下面看看JS是如何执行的。我们需要有一个容器div来保存要生成的类似图标。以及绑定点击事件的按钮:constcacheRef=useRef({bubbleCnt:null,likeIcon:null,bubbleIndex:0,timer:null,});useEffect(()=>{cacheRef.current.bubbleCnt=document.getElementById('like-bubble-cnt');cacheRef.current.likeIcon=document.getElementById('like-icon');},[]);在点击事件中,生成一个新的div元素,并设置为ItsetsclassName。然后追加到容器中,过段时间最后销毁like图标元素。如下:/***addbubble*/constaddBubble=()=>{const{bubbleCnt}=cacheRef.current;cacheRef.current.bubbleIndex%=maxBubble;constd=document.createElement('div');//图像类b0-b7//随机动画类bl_1_1-bl_3_2constswing=Math.floor(Math.random()*3)+1;constspeed=Math.floor(Math.random()*2)+1;d.className=`like-bubbleb${cacheRef.current.bubbleIndex}bl_${swing}_${speed}`;bubbleCnt?.appendChild(d);cacheRef.current.bubbleIndex++;//动画结束后销毁元素setTimeout(()=>{bubbleCnt?.removeChild(d);},2600);};在这一点上,我们几乎完成了。不过我们也可以给点击的图标加上一些动画,让它有按下后弹跳的效果:/***Click"Like"*/constonClick=()=>{const{timer,likeIcon}=cacheRef.current;if(!likeIcon){返回;}如果(计时器){clearTimeout(计时器);cacheRef.current.timer=null;}likeIcon.classList.remove('弹跳点击');//删除并重新添加类,需要延迟添加setTimeout(()=>{likeIcon.classList.add('bounce-click');},0);cacheRef.current.timer=window.setTimeout(()=>{likeIcon.classList.remove('bounce-click');clearTimeout(timer!);cacheRef.current.timer=null;},300);addBubble();};2.5最终效果最后,来看看效果吧!今天就到这里,下一期我会和大家分享canvas实现像动画的方法??欢迎大家关注我,文章小白在路上,你们是我继续整理分享的动力????公众号:前端别惹我????关注+点赞收藏+评论+分享??,手留余香,谢谢大家。