1. 程式人生 > >vue.js加入購物車小球動畫

vue.js加入購物車小球動畫

rect 獲取 最終 使用 off ood 實例 splay word

  • 生成一個動畫小球的div,並且生成五個小球,五個是為了生成一定數量的小球來作為操作使用,按照小球動畫的速度,一般來說五個也可以保證有足夠的小球數量來運行動畫

  • 動畫的內容分別是外層和內層,外層控制動畫小球的軌道和方向,內層控制動畫小球的運行狀態

  • 動畫使用vue的js鉤子實現

  • 因為小球動畫只有一個方向(只執行單方向從上到下滾落),所以只用了before-enter,enter,after-enter

  • 用v-show控制小球的可見性,在動畫執行期間可見,其余時候隱藏

  • <div class="ball-container">
    <transition name="fade" v-for="ball in balls"
    :key="ball.show"
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter">
    <div class="ball" v-show="ball.show">
    <div class="inner inner-hook"></div>
    </div>
    </transition>
    </div>
    • 設置了balls數組來代表五個小球

    • 設置了dropBalls數組正在運行的小球

data() {
return {
bar: ‘‘,
balls: [
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
}
],
dropBalls: []
}
}

      • 只要觸發了drop事件,不止是drop事件裏面的代碼會執行,另外幾個vue的js監聽鉤子也會一起按順序執行

        • 觸發了drop事件

        • beforeEnter開始執行

        • enter開始執行

        • afterEnter開始執行

      • drop事件的觸發可以通過點擊cartcontrol組件的添加小球按鈕addCart事件觸發使用$emit,也可以父組件this.$refs.shopcart.drop(target);直接觸發

        • 這麽做的目的是實現,在子組件cartcontrol點擊之後,可以將該dom傳給父組件goods然後再傳給子組件shopcart,(因為目前他們之間的通道就是這樣,shopcart子組件並沒有導入cartcontrol子組件,所以沒有直接通訊)這樣就實現了多個組件之間的通訊,從而可以實現需求,例如這裏就是實現點擊子組件cartcontrol後添加一個動畫,將小球滑落到另外一個組件shopcart

      • $emit是觸發當前實例上的事件。附加參數都會傳給監聽器回調。

methods: {
drop(el) {
console.log(‘子組件檢測到了‘, el)
for (let i = 0; i < this.balls.length; i++) {
let ball = this.balls[i]
if (!ball.show) { // 將false的小球放到dropBalls
ball.show = true
ball.el = el // 設置小球的el屬性為一個dom對象
this.dropBalls.push(ball)
return
}
}
},
beforeEnter(el) { // 這個方法的執行是因為這是一個vue的監聽事件
console.log(‘小球進入以前‘, el)
let count = this.balls.length
while (count--) {
let ball = this.balls[count]
if (ball.show) {
let rect = ball.el.getBoundingClientRect() // 獲取小球的相對於視口的位移(小球高度)
let x = rect.left - 32
let y = -(window.innerHeight - rect.top - 22) // 負數,因為是從左上角往下的的方向
console.log(x, y)
el.style.display = ‘‘ // 清空display
el.style.webkitTransform = `translate3d(0,${y}px,0)`
el.style.transform = `translate3d(0,${y}px,0)`
// 處理內層動畫
let inner = el.getElementsByClassName(‘inner-hook‘)[0] // 使用inner-hook類來單純被js操作
inner.style.webkitTransform = `translate3d(${x}px,0,0)`
inner.style.transform = `translate3d(${x}px,0,0)`
}
}
},
enter(el, done) { // 這個方法的執行是因為這是一個vue的監聽事件
console.log(‘小球進入中‘, el)
/* eslint-disable no-unused-vars */
let rf = el.offsetHeight // 觸發重繪html
this.$nextTick(() => { // 讓動畫效果異步執行,提高性能
el.style.webkitTransform = ‘translate3d(0,0,0)‘
el.style.transform = ‘translate3d(0,0,0)‘
// 處理內層動畫
let inner = el.getElementsByClassName(‘inner-hook‘)[0] // 使用inner-hook類來單純被js操作
inner.style.webkitTransform = ‘translate3d(0,0,0)‘
inner.style.transform = ‘translate3d(0,0,0)‘
el.addEventListener(‘transitionend‘, done) // Vue為了知道過渡的完成,必須設置相應的事件監聽器。
})
},
afterEnter(el) { // 這個方法的執行是因為這是一個vue的監聽事件
console.log(‘小球進入完成‘, el)
let ball = this.dropBalls.shift() // 完成一次動畫就刪除一個dropBalls的小球
if (ball) {
ball.show = false
el.style.display = ‘none‘ // 隱藏小球
}
}
}
  • 關於transitionend

  • 關於drop方法,是實現每一個ball的show屬性和el屬性處理,並且點擊一次會自動將一個小球放到dropBalls數組裏面,放到裏面就代表的是一個小球已經被開始執行動畫,但是由於動畫是異步的,所以先主動設置.

  • 關於getBoundingClientRect(位移的計算是從左上角開始)

    • 使用getBoundingClientRect獲取到當前元素的坐標,然後需要位移的left減去元素的寬獲取真正的最終位移x坐標

    • 使用getBoundingClientRect獲取到當前元素的坐標,然後需要當前屏幕的高度減去元素的top再減去元素本身的高度獲取到真正的最終位移y坐標,並且這個是負數,因為是從左上角往下的方向

  • 關於html重繪

    • 因為瀏覽器對於重繪是有要求並且是有隊列完成的,這是主要為了性能,雖然動畫隱藏了小球display none,但沒有觸發html重繪,或者說沒有立即觸發html重繪,所以需要手動

    • let rf = el.offsetHeight; 這是一個手動觸發html重繪的方法

    • 網頁性能管理詳解 http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html

    • 高性能JavaScript 重排與重繪http://www.cnblogs.com/zichi/p/4720000.html

.ball-container
.ball
position fixed
left: 32px
bottom: 22px
z-index:200
transition: all .6s cubic-bezier(0.49, -0.29, 0.75, 0.41)
.inner
width 16px
height 16px
border-radius 50%
background rgb(0,160,220)
transition: all .6s linear

關於cubic-bezier(0.49, -0.29, 0.75, 0.41),是動畫拋物曲線(貝塞爾曲線)的配置,基於css3實現,http://cubic-bezier.com/#.17,.67,.83,.67,參考貝塞爾曲線與CSS3動畫、SVG和canvas的基情 ,至於拋物線放在外層就是為了控制內層的元素的軌道和方向的.

原文地址:http://www.cnblogs.com/yuxingyoucan/p/7063881.html

vue.js加入購物車小球動畫