vue實現(xiàn)購物車拋物線小球動畫效果的方法詳解
本文實例講述了vue實現(xiàn)購物車拋物線小球動畫效果的方法。分享給大家供大家參考,具體如下:
先上最終效果圖,在商品頁面和商品詳情頁面點擊加號添加商品時都可以看到小球拋物線落入購物車的動畫效果
此文章只寫了商品頁面購物小球的實現(xiàn),商品詳情頁原理類似
實現(xiàn)步驟:
1. 需要三個組件,最下方包含藍色購物車的【購物車】組件shopCart.vue(子組件),每個【加減號】組成的購物小球組件cartControl.vue(子組件),和包含每個商品信息的goods組件goods.vue(父組件)
2. 原理,購物小球組件在點擊加號的時候?qū)ν庥|發(fā)事件,將小球?qū)ο蟊旧韨鬟f給父組件goods組件,再由goods作為橋梁將這個信息傳遞給另一個子組件shopCart組件,shopCart組件獲取到小球?qū)ο蠛?,對該小球進行位置計算,從而實現(xiàn)從不同商品的位置添加商品的拋物線小球效果
3. cartControl.vue部分代碼
html代碼
<div class="cartControl"> <transition name="move"> <!--減少商品--> <div class="decrease " v-show="food.count>0" @click.stop.prevent="decreaseCart"> <span class="inner iconfont"></span> </div> </transition> <!--增加商品--> <div class="count" v-show="food.count>0">{{food.count}}</div> <!--點擊加號按鈕,觸發(fā)事件addCart,將事件對象作為參數(shù)傳遞--> <div class="add iconfont" @click.stop.prevent="addCart($event)"></div> </div>
js代碼
// addCart事件 addCart (event) { if (!event._constructed) return // 檢測事件派發(fā)是否來自于better-scroll if (!this.food.count) { // 當給一個觀測對象添加一個它不存在的屬性的時候,直接賦值是不可以的,需要使用Vue.set設(shè)置這個屬性 Vue.set(this.food, 'count', 1) } else { this.food.count++ } this.$emit('cart-add', event.target) // 向父組件觸發(fā)一個自定義的cart-add事件,同時將事件對象傳遞給父組件 },
4. goods.vue部分代碼
html代碼
<!--加減商品--> <div class="cartControl-wrapper"> <!--在父組件監(jiān)聽到子組件觸發(fā)的cart-add事件--> <cart-control :food="food" @cart-add="handlecartAdd"></cart-control> </div>
js代碼 知識點:子組件和父組件之間的數(shù)據(jù)傳遞
_drop (target) { // 在goods.vue定義 _drop方法將cartcontrol的傳遞過來target對象再傳遞給shopCart this.$nextTick(() => { // 使用$nextTick優(yōu)化體驗 this.$refs.shopCart.drop(target) // 父組件goods通過.$refs屬性訪問shopCart子組件的drop方法 }) }, handlecartAdd (target) { // 點擊加號按鈕觸發(fā)事件 this._drop(target) // 調(diào)用_drop方法 }
5. shopCart.vue部分代碼
①.定義一個數(shù)組,存放5個小球,這5個小球可以滿足的動畫的運行
②.動畫分為兩層,外層控制小球y軸方向和運動的軌道,內(nèi)層控制x軸方向的運動
③.使用js動畫鉤子,vue在實現(xiàn)動畫的時候提供了幾個javascript鉤子,可配合css動畫一起使用,也可單獨使用,因為購物車拋物線小球只有進入動畫,沒有離開的動畫,所以enter的鉤子有,before-enter,enter,after-enter,這些鉤子需要在html屬性中聲明,然后在methods中使用這些方法
可參考以下官網(wǎng)
https://cn.vuejs.org/v2/guide/transitions.html#JavaScript-%E9%92%A9%E5%AD%90
④.v-show控制盒子的顯示和隱藏
html
<!--購物車小球--> <div class="ball-container"> <div v-for="(ball,index) of balls" :key="index"> <transition @before-enter="handleBeforeEnter" @enter="handleEnter" @after-enter="handleAfterEnter"> <div class="ball" v-show="ball.show" v-bind:css="false"><!--外層盒子--> <div class="inner inner-hook"></div> <!--內(nèi)層盒子--> </div> </transition> </div> </div>
data
data () { return { // 使用balls存放5個小球,這些小球的默認狀態(tài)都是不顯示的 balls: [{show: false}, {show: false}, {show: false}, {show: false}, {show: false}], dropBalls: [] // 用dropBalls來存放掉落的小球 } }
在methods中定義方法
// 當觸發(fā)drop方法時小球開始掉落 drop (el) { for (let i = 0; i < this.balls.length; i++) { // 遍歷這5個小球 let ball = this.balls[i] if (!ball.show) { // 當小球顯示狀態(tài)為隱藏時 ball.show = true // 將這個小球的顯示狀態(tài)設(shè)置為true ball.el = el // 將cartControl傳過來的對象掛載到ball的el屬性上 this.dropBalls.push(ball) // 將這個小球放入到dropBalls數(shù)組中 return } } }
js動畫
// js動畫鉤子 // beforeenter handleBeforeEnter: function (el) { let count = this.balls.length while (count--) { let ball = this.balls[count] if (ball.show) { let rect = ball.el.getBoundingClientRect() // getBoundingClientRect()獲取小球相對于視窗的位置,屏幕左上角坐標為0,0 let x = rect.left - 32 // 小球x方向位移= 小球距離屏幕左側(cè)的距離-外層盒子距離水平的距離 let y = -(window.innerHeight - rect.top - 22) // 負數(shù),因為是從左上角向下 el.style.display = '' el.style.webkitTransform = `translate3d(0,${y}px,0)` // 設(shè)置外層盒子,即小球垂直方向的位移 el.style.transform = `translate3d(0,${y}px,0)` let inner = el.getElementsByClassName('inner-hook')[0] inner.style.webkitTransform = `translate3d(${x}px,0,0)` // 設(shè)置內(nèi)層盒子,即小球水平方向的距離 inner.style.transform = `translate3d(${x}px,0,0)` } } }, // enter handleEnter: function (el, done) { /* eslint-disable no-unused-vars */ // 觸發(fā)瀏覽器重繪 let rf = el.offsetHeight this.$nextTick(() => { // 讓動畫效果異步執(zhí)行,提高性能 el.style.webkitTransform = 'translate3d(0, 0, 0)'// 設(shè)置小球掉落后最終的位置 el.style.transform = 'translate3d(0, 0, 0)' let inner = el.getElementsByClassName('inner-hook')[0] inner.style.webkitTransform = 'translate3d(0, 0, 0)' inner.style.transform = 'translate3d(0, 0, 0)' el.addEventListener('transitionend', done) // Vue為了知道過渡的完成,必須設(shè)置相應(yīng)的事件監(jiān)聽器。它可以是transitionend或 animationend }) }, handleAfterEnter: function (el) { let ball = this.dropBalls.shift() // 完成一次動畫就刪除一個dropBalls的小球 if (ball) { ball.show = false el.style.display = 'none' } },
希望本文所述對大家vue.js程序設(shè)計有所幫助。
相關(guān)文章
Vue3學(xué)習(xí)筆記之依賴注入Provide/Inject
provide和inject可以實現(xiàn)嵌套組件之間進行傳遞數(shù)據(jù),這兩個函數(shù)都是在setup函數(shù)中使用的,下面這篇文章主要給大家介紹了關(guān)于Vue3學(xué)習(xí)筆記之依賴注入Provide?/?Inject的相關(guān)資料,需要的朋友可以參考下2023-05-05Vue 中使用vue2-highcharts實現(xiàn)曲線數(shù)據(jù)展示的方法
下面小編就為大家分享一篇Vue 中使用vue2-highcharts實現(xiàn)曲線數(shù)據(jù)展示的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03vue+elementUI實現(xiàn)動態(tài)面包屑
這篇文章主要為大家詳細介紹了vue+elementUI實現(xiàn)動態(tài)面包屑,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04Vue實現(xiàn)讓頁面加載時請求后臺接口數(shù)據(jù)
這篇文章主要介紹了Vue實現(xiàn)讓頁面加載時請求后臺接口數(shù)據(jù)2022-08-08Vue打包程序部署到Nginx 點擊跳轉(zhuǎn)404問題
這篇文章主要介紹了Vue打包程序部署到Nginx 點擊跳轉(zhuǎn)404問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Vue+axios使用FormData方式向后端發(fā)送數(shù)據(jù)
在前后端分離的項目中經(jīng)常使用到Vue+axios通過FormData的方式向后端發(fā)送表單數(shù)據(jù),下面就來介紹一下如何實現(xiàn),感興趣的可以了解一下2023-09-09解決element-ui的el-dialog組件中調(diào)用ref無效的問題
這篇文章主要介紹了解決element-ui的el-dialog組件中調(diào)用ref無效的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02