github源碼地址:https://github.com/13476075014/node-vue/tree/master/mynodeproject/13.sell/sell
在移動端經常會有加入購物車,小球飛入的動畫效果,具體如下圖,圖片略微拙劣,我自己截自己寫的小效果的,,,
一:小球的html代碼如下:
<!-- 加入購入車按鈕的小球動畫實現 -->
<div class="ball-container">
<transition v-on:after-enter="afterEnter" v-on:enter="enter" v-on:before-enter="beforeEnter" name="drop" v-for="(litterBall,indexBall) in balls" :key="indexBall">
<div v-show="litterBall.show" class="ball">
<div class="inner" :class="indexBall">
</div>
</div>
</transition>
</div>
* 小球用的 transition標簽包住的,在上面寫上vue的javascript動畫生命鈎子
v-on:before-enter="beforeEnter" (動畫進入前)
v-on:enter="enter"(動畫進入時)
v-on:after-enter="afterEnter" (動畫進入完后)
二:js部分
2.1 在data里面加上小球的數據,這里准備了比較多的,可以在有人點着玩的時候,很快速的點也盡量不出現bug:
export default { name:"goods", data(){ return { ......, //別的數據 balls:[//小球 {show:false,index:0}, {show:false,index:1}, {show:false,index:2}, {show:false,index:3}, {show:false,index:4}, {show:false,index:5}, {show:false,index:6}, {show:false,index:7}, {show:false,index:8}, {show:false,index:9}, {show:false,index:10}, {show:false,index:11} ], dropBall:[] //已經在下降的小球存在這里 } }
2.2 在methods 中寫入加入購物車的加號點擊時候的小球部分的方法,把點擊的元素存在data的balls中,便於后面獲取其位置,把小球展示出來:
methods:{ ...... //別的一些方法 , drop(el){//小球動畫方法,el就是加號按鈕元素 for(var i=0;i<this.balls.length;i++){ if(!this.balls[i].show){//把小球show為false的變成true,展示出來 let ball = this.balls[i]; ball.show = true; //這里這樣寫他繼承的this.balls的值也會變成true ball.el = el; //把這個球的位置保留下來 this.dropBall.push(ball); //把這個已經drop的球放到dropBall中 //console.log(this.dropBall,222) return //結束循環和函數,不會讓循環再往后執行了 } } }, ..... //別的一些方法 }
2.3 在 metholds中寫入 transition動畫的幾個javascript生命鈎子函數方法:
methods:{ ....... //別的方法省略,具體看github上有源代碼 , beforeEnter(els){ let count = this.dropBall.length -1 ; //獲取要下降中的小球個數 let ball = this.dropBall[count]; //獲取最新點擊成show:true的小球 let rect = ball.el.getBoundingClientRect(); //getBoundingClientRect()可以獲取到元素對象和窗口的相對上下左右的距離 var rect2 = els.getBoundingClientRect(); let x = rect.left - 18 ; //點擊元素的左邊距離 - 下面購物車左邊的距離,就是小球要運動的X軸距離 let y =-(window.innerHeight - rect.top -32) ;//窗口的高度 - 點擊元素離窗口的高度 - 購物車底部的padding,margin高度,就是小球要運動的y軸距離,且是向下運動,所以是負值 //els.style.display =""; els.style.opacity = 1; els.style.webkitTransform = `translate3d(0,${y}px,0)`; els.style.transform = `translate3d(0,${y}px,0)`; //外層做縱軸運動 //內層做橫軸運動 let inner = els.getElementsByClassName('inner')[0]; inner.style.webkitTransform = `translate3d(${x}px,0,0)`; inner.style.transform = `translate3d(${x}px,0,0)`; }, enter(els,done){ var _this = this; let hh = els.offsetHeight; //手動獲取這個值,觸發瀏覽器重繪 _this.$nextTick(function(){ //內層做橫軸運動 els.style.opacity = "0"; let inner = els.getElementsByClassName('inner')[0]; Velocity(els,{translate3d:"translate3d(0,0,0)"},{duration:600}); //這里引入了第三方動畫插件,需要先 npm i velocity-animate --save ,和 引入 import Velocity from 'velocity-animate'
Velocity(inner,{translate3d:"translate3d(0,0,0)"},{duration:600,complete:function(){ done(); } }); }); }, afterEnter(els){ let ball = this.dropBall.shift(); if(ball){ ball.show = false; els.style.display = "none"; //這個很重要 } }, ...... //一些別的方法 }
三:css部分
/*用的stylus編譯 */
.ball-container .ball position fixed left 32px bottom 22px z-index 900 transform translate3d(0,0,0) transition all 0.6s cubic-bezier(0.49,-0.29,0.75,0.41) //這個很重要,要變成曲線就需要這個貝賽爾曲線 .inner width 16px height 16px border-radius 100% background rgb(0,160,220) transition all 0.6s linear transform translate3d(0,0,0)