之前写过一次类似树叶落下的效果,当时想到的方法是,动态的往body里面添加元素,添加一些随机的属性,然后写一个动画,让他按照随机的速度落下,达到一种落差的效果,最后判断top值是否超过clientHeight,超过就remove掉。
嗯,看样子不错,也能跑起来,但是在安卓手机上测试,会有卡顿,后来优化了下,改成css3动画,再次测试,不错,安卓也不卡了,挺流畅,但是代码量又增加了,并且这样反复的对dom进行属性的重绘,添加和删除,效率很低。
今天换了另一种写法,所有动画效果全部利用css3来完成,也不用反复的进行dom添加和删除操作了,并且代码量是之前的三分之一。先看下面的演示效果吧。
那么先从html结构开始说,下面就是树叶dom的结构,暂时把每个div称作leaves :
- <div class=“leaves”><img src=“img1.png” alt=“”></div>
下面是css部分,让每一个leaves都absolute定位,top为-100px,让他置于窗口外面隐藏起来:
- .leaves{width: 80px;height: auto; position: absolute; left: 0px; top: –80px;}
- .leaves img{width: 100%;}
接下来就开始写css3动画了,要想leaves从上落下,需要使用keyframes关键帧动画,让他0%的时候从0开始,100%的时候,落到650px处,然后在css中添加animation:move 6s linear infinite,让他6秒重复播放(具体animation的使用,查阅w3c介绍):
- //记住兼容性,需要添加moz和webkit前缀
- @keyframes move
- {
- 0% {transform: translate3d(0px, 0px,0); }
- 100% {transform: translate3d(0px, 650px,0); }
- }
落下的效果就算写好了,由于定位的关系,他们可能全部挤在一起,这个等下通过js来改变left值,接下来让他到最下面的慢慢消失,这个其实就是opacity透明,当然也是需要keyframes关键帧动画的,到100%的时候opacity为0,时间跟上面move落下的时间需要一致,animation:fade 6s linear infinite:
- //记住兼容性,需要添加moz和webkit前缀
- @keyframes fade
- {
- 0% { opacity: 1; }
- 50% { opacity: 1; }
- 100% { opacity: 0; }
- }
到目前为止,基本css都已经写好了,但是貌似还少了点什么,看看上面的demo,原来是少了左右摇摆,摇摆可以使用rotate旋转,我们给leaves里面的img添加keyframes关键帧动画【因为leaves已经有transform动画,如果这里在添加rotate会覆盖前面的】,在css中添加animation:rotate 3s ease-in-out infinite alternate。
- @keyframes rotate
- {
- 0% { transform:rotate(-50deg); }
- 100% { transform:rotate(50deg); }
- }
- //这是翻转元素,让树叶看起来多种多样
- @keyframes rotate1
- {
- 0% { transform:scale(-1, 1) rotate(-50deg); }
- 100% { transform:scale(-1, 1) rotate(50deg); }
- }
需要注意的是:默认rotate的旋转基点再元素的中心,这样摆起来很怪异,使用transform-origin:50% -100%;来改变他的旋转基点,看起来就很自然,慢慢悠悠落下的感觉,在css中修改:
- .leaves img{transform-origin:50% -100%;-moz-transform-origin:50% -100%;-webkit-transform-origin:50% -100%;width: 100%;}
如果只是这样css写,所有的leaves会一起落下,并没有上面demo那样参差不齐的感觉,那是因为所有leaves的动画时间都是一样的,现在我们需要通过js来改变每个leaves落下的时间,以及延时时间就可以了:
提示:如果你的leaves是直接写在html中的,可以忽略下面的代码,如果你想动态添加到body中,可以看下面的代码:
- //树叶的总个数
- var count = 20;
- //循环创建树叶的dom元素
- var fragment = document.createDocumentFragment();
- for(var i = 0 ; i < count; i ++) {
- var div = document.createElement(“div”);
- div.className = ‘leaves’;
- div.innerHTML = ‘<img src=“img’+(Math.round(Random(1,3)))+’.png” alt=“”>’;
- fragment.appendChild (div);
- };
- //添加到body里
- document.body.appendChild(fragment);
下面是一个Random获取随机数的函数,用于改变每个leaves的left值,以及动画时间:
- function Random(s,e){return Math.random()*(e-s)+s;};
接着通过js获取所有leaves:
- var leaves = document.querySelectorAll(‘.leaves’);
然后使用forEach循环每个leaves,来修改动画时间,延时时间,还有摇摆的时间,让他们看起来有落差,从视觉上看像树叶一片片落下的感觉:
- [].forEach.call(leaves,function(o,i){
- var time1 = Random(5,10); //树叶总共落下的时间
- var time2 = Random(1,3); //每个树叶的延时时间
- var time3 = Random(3,6); //每个树叶的摇摆的时间
- //随机设置left,根据浏览器宽度设置最大值
- o.style.left = Random(-30,document.documentElement.clientWidth) +’px’;
- //设置animation属性,为了兼容添加了前缀,总共时间和延时时间随机获取
- o.style.animation = o.style.WebkitAnimation = o.style.MozAnimation = ‘fade ‘+time1+’s ‘+ time2+’s linear infinite,move ‘+time1+’s ‘+ time2+’s linear infinite’;
- //设置里面图片的animation属性,设置摇摆时间,随机翻转树叶
- o.children[0].style.animation = o.children[0].style.MozAnimation = o.children[0].style.WebkitAnimation = Math.round(Random(0,1)) ? ‘rotate ‘+time3+’s ease-in-out infinite alternate’ : ‘rotate1 ‘+time3+’s ease-in-out infinite alternate’;
- })
到此,树叶飘落的动画效果以及全部写完,可以稍微修改,来实现金币效果,下雪效果…..
不错 😛