vue實(shí)現(xiàn)購物車拋物線小球動(dòng)畫效果的方法詳解
本文實(shí)例講述了vue實(shí)現(xiàn)購物車拋物線小球動(dòng)畫效果的方法。分享給大家供大家參考,具體如下:
先上最終效果圖,在商品頁面和商品詳情頁面點(diǎn)擊加號(hào)添加商品時(shí)都可以看到小球拋物線落入購物車的動(dòng)畫效果
此文章只寫了商品頁面購物小球的實(shí)現(xiàn),商品詳情頁原理類似
實(shí)現(xiàn)步驟:
1. 需要三個(gè)組件,最下方包含藍(lán)色購物車的【購物車】組件shopCart.vue(子組件),每個(gè)【加減號(hào)】組成的購物小球組件cartControl.vue(子組件),和包含每個(gè)商品信息的goods組件goods.vue(父組件)
2. 原理,購物小球組件在點(diǎn)擊加號(hào)的時(shí)候?qū)ν庥|發(fā)事件,將小球?qū)ο蟊旧韨鬟f給父組件goods組件,再由goods作為橋梁將這個(gè)信息傳遞給另一個(gè)子組件shopCart組件,shopCart組件獲取到小球?qū)ο蠛?,?duì)該小球進(jìn)行位置計(jì)算,從而實(shí)現(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> <!--點(diǎn)擊加號(hào)按鈕,觸發(fā)事件addCart,將事件對(duì)象作為參數(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) { // 當(dāng)給一個(gè)觀測對(duì)象添加一個(gè)它不存在的屬性的時(shí)候,直接賦值是不可以的,需要使用Vue.set設(shè)置這個(gè)屬性 Vue.set(this.food, 'count', 1) } else { this.food.count++ } this.$emit('cart-add', event.target) // 向父組件觸發(fā)一個(gè)自定義的cart-add事件,同時(shí)將事件對(duì)象傳遞給父組件 },
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í)點(diǎn):子組件和父組件之間的數(shù)據(jù)傳遞
_drop (target) { // 在goods.vue定義 _drop方法將cartcontrol的傳遞過來target對(duì)象再傳遞給shopCart this.$nextTick(() => { // 使用$nextTick優(yōu)化體驗(yàn) this.$refs.shopCart.drop(target) // 父組件goods通過.$refs屬性訪問shopCart子組件的drop方法 }) }, handlecartAdd (target) { // 點(diǎn)擊加號(hào)按鈕觸發(fā)事件 this._drop(target) // 調(diào)用_drop方法 }
5. shopCart.vue部分代碼
①.定義一個(gè)數(shù)組,存放5個(gè)小球,這5個(gè)小球可以滿足的動(dòng)畫的運(yùn)行
②.動(dòng)畫分為兩層,外層控制小球y軸方向和運(yùn)動(dòng)的軌道,內(nèi)層控制x軸方向的運(yùn)動(dòng)
③.使用js動(dòng)畫鉤子,vue在實(shí)現(xiàn)動(dòng)畫的時(shí)候提供了幾個(gè)javascript鉤子,可配合css動(dòng)畫一起使用,也可單獨(dú)使用,因?yàn)橘徫镘噿佄锞€小球只有進(jìn)入動(dòng)畫,沒有離開的動(dòng)畫,所以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個(gè)小球,這些小球的默認(rèn)狀態(tài)都是不顯示的 balls: [{show: false}, {show: false}, {show: false}, {show: false}, {show: false}], dropBalls: [] // 用dropBalls來存放掉落的小球 } }
在methods中定義方法
// 當(dāng)觸發(fā)drop方法時(shí)小球開始掉落 drop (el) { for (let i = 0; i < this.balls.length; i++) { // 遍歷這5個(gè)小球 let ball = this.balls[i] if (!ball.show) { // 當(dāng)小球顯示狀態(tài)為隱藏時(shí) ball.show = true // 將這個(gè)小球的顯示狀態(tài)設(shè)置為true ball.el = el // 將cartControl傳過來的對(duì)象掛載到ball的el屬性上 this.dropBalls.push(ball) // 將這個(gè)小球放入到dropBalls數(shù)組中 return } } }
js動(dòng)畫
// js動(dòng)畫鉤子 // 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()獲取小球相對(duì)于視窗的位置,屏幕左上角坐標(biāo)為0,0 let x = rect.left - 32 // 小球x方向位移= 小球距離屏幕左側(cè)的距離-外層盒子距離水平的距離 let y = -(window.innerHeight - rect.top - 22) // 負(fù)數(shù),因?yàn)槭菑淖笊辖窍蛳? 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(() => { // 讓動(dòng)畫效果異步執(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() // 完成一次動(dòng)畫就刪除一個(gè)dropBalls的小球 if (ball) { ball.show = false el.style.display = 'none' } },
希望本文所述對(duì)大家vue.js程序設(shè)計(jì)有所幫助。
相關(guān)文章
Vue3學(xué)習(xí)筆記之依賴注入Provide/Inject
provide和inject可以實(shí)現(xiàn)嵌套組件之間進(jìn)行傳遞數(shù)據(jù),這兩個(gè)函數(shù)都是在setup函數(shù)中使用的,下面這篇文章主要給大家介紹了關(guān)于Vue3學(xué)習(xí)筆記之依賴注入Provide?/?Inject的相關(guān)資料,需要的朋友可以參考下2023-05-05Vue 中使用vue2-highcharts實(shí)現(xiàn)曲線數(shù)據(jù)展示的方法
下面小編就為大家分享一篇Vue 中使用vue2-highcharts實(shí)現(xiàn)曲線數(shù)據(jù)展示的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-03-03vue+elementUI實(shí)現(xiàn)動(dòng)態(tài)面包屑
這篇文章主要為大家詳細(xì)介紹了vue+elementUI實(shí)現(xiàn)動(dòng)態(tài)面包屑,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04Vue實(shí)現(xiàn)讓頁面加載時(shí)請(qǐng)求后臺(tái)接口數(shù)據(jù)
這篇文章主要介紹了Vue實(shí)現(xiàn)讓頁面加載時(shí)請(qǐng)求后臺(tái)接口數(shù)據(jù)2022-08-08Vue打包程序部署到Nginx 點(diǎn)擊跳轉(zhuǎn)404問題
這篇文章主要介紹了Vue打包程序部署到Nginx 點(diǎn)擊跳轉(zhuǎn)404問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02vue單個(gè)組件實(shí)現(xiàn)無限層級(jí)多選菜單功能
這篇文章主要介紹了vue單個(gè)組件實(shí)現(xiàn)無限層級(jí)多選菜單的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-04-04Vue+axios使用FormData方式向后端發(fā)送數(shù)據(jù)
在前后端分離的項(xiàng)目中經(jīng)常使用到Vue+axios通過FormData的方式向后端發(fā)送表單數(shù)據(jù),下面就來介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下2023-09-09解決element-ui的el-dialog組件中調(diào)用ref無效的問題
這篇文章主要介紹了解決element-ui的el-dialog組件中調(diào)用ref無效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-02-02