动画动效之收发牌特效
一、收发牌
需求
5张卡片,上3下2,需要触发页面按钮后,卡片全部回收到按钮处,然后在发出来,类似洗牌的效果。
思路
最近活动需求,要实现一种类似蜘蛛纸牌收发牌的类似动效。查阅资料后,发现满足雪球的话,卡片(下文“牌”都用“卡片”代替)数量不多,可以使用css的translate3d实现。
效果图
*H5
卡片是由一个外层的div和内层的img组成,点击按钮,触发动画之后,外层的div通过translate3d移动位置,内层的img进行缩放。
重点是在动画这里,img缩放和div平移的动画时间一致,div是先平移到按钮处,这时候img缩小,刚好被按钮遮挡,省去了我们需要隐藏img的逻辑。通过定时器,让每个卡片的动画执行时间都比前一个晚一点,就会形成卡片一个一个收起,一个一个在发出去的效果。20%-80%效果一样,就是让img缩小,平移到按钮下面时,停留一会,待所有卡片都收起后,再顺序发出。
.blindimgan{ animation: blindimgcla 2s linear 1; } @keyframes blindimgcla { 0% { transform: scale(1); } 20% { transform: scale(0.1); } 40% { transform: scale(0.1); } 60% { transform: scale(0.1); } 80% { transform: scale(0.1); } 100% { transform: scale(1); } } .blindboxlian1{ animation: blindboxlicla1 2s linear 1; } @keyframes blindboxlicla1 { 0% { transform: translate3d(0,0,0); } 20% { transform: translate3d(2rem,6rem,0); } 40% { transform: translate3d(2rem,6rem,0); } 60% { transform: translate3d(2rem,6rem,0); } 80% { transform: translate3d(2rem,6rem,0); } 100% { transform: translate3d(0,0,0); } } .blindboxlian2{ animation: blindboxlicla2 2s linear 1; } @keyframes blindboxlicla2 { 0% { transform: translate3d(0,0,0); } 20% { transform: translate3d(0,6rem,0); } 40% { transform: translate3d(0,6rem,0); } 60% { transform: translate3d(0,6rem,0); } 80% { transform: translate3d(0,6rem,0); } 100% { transform: translate3d(0,0,0); } } .blindboxlian3{ animation: blindboxlicla3 2s linear 1; } @keyframes blindboxlicla3 { 0% { transform: translate3d(0,0,0); } 20% { transform: translate3d(-2rem,6rem,0); } 40% { transform: translate3d(-2rem,6rem,0); } 60% { transform: translate3d(-2rem,6rem,0); } 80% { transform: translate3d(-2rem,6rem,0); } 100% { transform: translate3d(0,0,0); } } .blindboxlian4{ animation: blindboxlicla4 2s linear 1; } @keyframes blindboxlicla4 { 0% { transform: translate3d(0,0,0); } 20% { transform: translate3d(1rem,3rem,0); } 40% { transform: translate3d(1rem,3rem,0); } 60% { transform: translate3d(1rem,3rem,0); } 80% { transform: translate3d(1rem,3rem,0); } 100% { transform: translate3d(0,0,0); } } .blindboxlian5{ animation: blindboxlicla5 2s linear 1; } @keyframes blindboxlicla5 { 0% { transform: translate3d(0,0,0); } 20% { transform: translate3d(-1rem,3rem,0); } 40% { transform: translate3d(-1rem,3rem,0); } 60% { transform: translate3d(-1rem,3rem,0); } 80% { transform: translate3d(-1rem,3rem,0); } 100% { transform: translate3d(0,0,0); } }
不要问我,为什么用这么多定时器,(我乐意),其实也可以使用css的animation的延时,效果是一样的。
//开始动画 setTimeout(function(){ $(".blindboxli1").addClass("blindboxlian1"); $(".blindboxli1>.blindimg0").addClass("blindimgan"); setTimeout(function(){ $(".blindboxli2").addClass("blindboxlian2"); $(".blindboxli2>.blindimg0").addClass("blindimgan"); setTimeout(function(){ $(".blindboxli3").addClass("blindboxlian3"); $(".blindboxli3>.blindimg0").addClass("blindimgan"); setTimeout(function(){ $(".blindboxli4").addClass("blindboxlian4"); $(".blindboxli4>.blindimg0").addClass("blindimgan"); setTimeout(function(){ $(".blindboxli5").addClass("blindboxlian5"); $(".blindboxli5>.blindimg0").addClass("blindimgan"); setTimeout(function(){ //按钮隐藏 $(".blindboxbtndiv").hide(); //收发卡动画结束,做相关处理 },2000); },100); },100); },100); },100); },100);
translate3d
translate3d
*小程序
小程序实现思路和H5是一样的,区别就是,动画是使用小程序自带的animate实现的。
// 收卡发卡特效 onClickBlindBox:function(){ var that = this; var blindBoxList = that.data.blindBoxList; var list1 = [ {translate3d: [0,0,0]}, {translate3d: [110,300,0]}, ]; var listNo1 = [ {translate3d: [110,300,0]}, {translate3d: [0,0,0]}, ]; that.blindBoxAn(1,list1,listNo1); var list2 = [ {translate3d: [0,0,0]}, {translate3d: [0,300,0]}, ]; var listNo2 = [ {translate3d: [0,300,0]}, {translate3d: [0,0,0]}, ]; setTimeout(function(){ that.blindBoxAn(2,list2,listNo2); },100) var list3 = [ {translate3d: [0,0,0]}, {translate3d: [-110,300,0]}, ]; var listNo3 = [ {translate3d: [-110,300,0]}, {translate3d: [0,0,0]}, ]; setTimeout(function(){ that.blindBoxAn(3,list3,listNo3); },200) var list4 = [ {translate3d: [0,0,0]}, {translate3d: [55,150,0]}, ]; var listNo4 = [ {translate3d: [55,150,0]}, {translate3d: [0,0,0]}, ]; setTimeout(function(){ that.blindBoxAn(4,list4,listNo4); },300) var list5 = [ {translate3d: [0,0,0]}, {translate3d: [-55,150,0]}, ]; var listNo5 = [ {translate3d: [-55,150,0]}, {translate3d: [0,0,0]}, ]; setTimeout(function(){ that.blindBoxAn(5,list5,listNo5); setTimeout(function(){ that.setData({ isBlindBoxBtn: 2 }) },2000); },400); }, //具体动画实现 blindBoxAn:function(str,list,listNo){ var that = this; var cla = ".blindboxli" + str; var cla1 = ".blindboxli" + str + ">.blindimg0"; that.animate(cla, list, 800, function() { that.clearAnimation(cla, {}, null) if(listNo){ setTimeout(function(){ that.animate(cla, listNo, 800, function() { that.clearAnimation(cla, {}, null) }.bind(that)); that.animate(cla1, [ {scale: [0.1, 0.1]}, {scale: [1,1]}, ], 800, function() { that.clearAnimation(cla1, {}, null) }.bind(that)); },500); } }.bind(that)); that.animate(cla1, [ {scale: [1,1]}, {scale: [0.1, 0.1]}, ], 800, function() { that.clearAnimation(cla1, {}, null) }.bind(that)); },
onClickBlindBox函数中,主要是animate动画执行需要数据,blindBoxAn是动画调用。
和H5动画效果和逻辑保持一致,但是小程序animate不好执行动画在一个地方一直等待的效果(没有那么流畅和好看),因此这里动画分两次,首次view(同div)平移,img缩小,使用定时器,等所有卡片收回后,在执行二次动画,view平移原先位置,img放大。
二、翻牌/翻卡片
既然有了收发卡片的效果,那必然会有翻卡片的效果。翻卡就会用到backface-visibility.
思路
把翻卡前(卡1)和翻卡后(卡2)的两张img定位到同一个位置,都设置backface-visibility: hidden;在给卡2的添加
transform: rotateY(-180deg);这样使用backface-visibility的特性,使卡2的img背面向屏幕,不可见。
点击卡1时,卡2设置visibility:visible,同时卡1transform: rotateY(180deg);卡2transform: rotateY(0);
实现卡片翻转,然后变成另一张卡的效果。
效果图