您好,登錄后才能下訂單哦!
各位掘友,好久不見,最近利用工作之余開源了Vue電商項目,高仿某知名O2O買菜平臺,整個項目做下來收獲還是蠻多的,可以掃描下方二維碼體驗,本篇是項目的核心知識拆解篇,主要是拆解增加商品飛入購物車的實現過程。
點我體驗
項目開源地址 感謝點星+收藏
首先我先簡單的介紹下本項目所用到的技術棧:
整個項目采用 vue-cli3 腳手架搭建, Vue全家桶(vue、vuex、vue-router) 、 Vant UI框架 以及很多著名好用的第三方庫如: axios 、 fastclick 、 better-scroll 、 twix.js 、 pubsub.js 、 moment.js 、 vue-amap 等等。 像素單位選擇 rem ,后臺數據接口通過 Easy-Mock 搭建,以最接近企業開發的方式,組件化模塊化,最大程度實現高內聚低耦合,大大提升各模塊的可維護及可擴展性,相信讀完源碼和我寫的系列拆解文章,無論你是哪個段位的攻城獅都會有所啟發!開源不易,你的點贊就是對我最大的鼓勵:tada::tada:感謝~Thanks♪(・ω・)ノ
首先先來瞅瞅要做成的樣子,是不是很炫酷:airplane::airplane:隨手點贊支持下作者:heartbeat:
實現思路
首先我們先來把關注點放到加入購物車這塊,當我們點擊購物車圖標的時候,這個時候會在當前點擊的商品圖片的中央范圍先出現個圓形的商品縮略圖,其次這個商品縮略圖會沿著當前位置以曲線的形式逐漸變小飛入到購物車里,當商品飛入到購物車時,購物車的數字圖標會增加,同時購物車會出現彈簧動畫。
通過上面大白話分析整個實現步驟可簡短分為三個階段來完成編碼:
第一階段編碼:繪制一個圓形的小球到商品的中間區域 這個非常簡單,就是在商品圖片區域加一個 div
,設置 position:fixed
及寬度高度等,但是呢?
先埋個問題,如何讓小球出現在點擊當前商品的范圍內呢?
起初我通過計算屬性遍歷了商品列表,在所有的商品視圖中加入商品縮略圖小球,然后,通過給每個商品列表里增加一個boolean屬性 show
,通過點擊購物車圖標來控制我剛創建的小球的顯示與隱藏,然后自己就進入了死胡同,饒了半天,計算屬性的數據通過 set
方式改變后,Dom死活不聽話就是不按套路出牌(因為計算屬性存在數據緩存),于是不得已放棄此笨拙的辦法。
上面踩坑是因為貪多,想一次性到位,提前加載所有商品的小球縮略圖,然后通過點擊購物車來控制當前商品縮略圖的顯示與隱藏.那么我們要不換一種思路,僅創建一個縮略小球怎么樣,通過 boolean
來控制它的顯示和隱藏,位置動態變化,點擊哪個商品就讓他顯示到哪個商品的范圍內,并且每次點擊給他設置個true的屬性丟到一個數組中.好,我們先在data中定義小球是否顯示的屬性及顯示小球的數組
data () { return { showMoveDot: [], //控制下落的小圓點顯示隱藏 }
然后我們在點擊購物車的時候來給 showMoveDot
數組動態增加屬性,然后在Dom中遍歷這個數組,雙向綁定,最后通過 v-if
來控制顯示和隱藏,這樣是不是非常妙~~
點擊購物車給 showMoveDot
增加 true
的屬性
methods: { addToCart (product, num) { this.showMoveDot = [...this.showMoveDot, true]; } }
Dom中遍歷 showMoveDot
,并且通過 v-if
來控制商品縮略小球的顯示
<div v-for="(item,index) in showMoveDot" :key="index"> <div class="move_dot" ref="ball" v-if="item"> </div> </div>
此時點擊購物車圖標就會在當前商品中出現商品縮略圖的小球,至此,階段一大功告成 ✿✿ヽ(°▽°)ノ✿ ~
本階段需要用到動畫知識,所以首先想到的是Vue的 transition 屬性,首先給縮略圖的小球包一層 transition
并且增加 appear
動畫并且實現 beforeEnter
、 afterEnter
事件方法,所以此時修改Dom代碼
<transition appear @before-appear="beforeEnter" @after-appear='afterEnter' v-for="(item,index) in showMoveDot" :key="index.id"> <div class="move_dot" ref="ball" v-if="item"> </div> </transition>
上面Dom代碼的兩個方法 beforeEnter
和 afterEnter
方法分別是動畫初次渲染前和動畫渲染后,那么我們就要把注意點放到這兩個狀態中. 在初次渲染的時候我們確定下小球的位置,那么這個時候我們就要用到一個方法 getBoundingClientRect ,這個方法返回的是一組矩形的集合,這下就好啦,可以通過這個方法來定位某個元素在屏幕中的位置啦:blush:~
那好,那我們這個時候就成熱打鐵,通過這個方法先來確定點擊購物車圖標的時候,購物車這個小圖標距左邊和頂部相對屏幕的距離。
定義兩個 data
來接受點擊增加購物車圖標獲取到的值.
data () { return { showMoveDot: [], //控制下落的小圓點顯示隱藏 elLeft: 0, //當前點擊購物車按鈕在網頁中的絕對top值 elTop: 0, //當前點擊購物車按鈕在網頁中的絕對left值 }
然后我們在點擊添加購物車的方法里獲取位置。
methods: { addToCart () { this.showMoveDot = [...this.showMoveDot, true]; this.elLeft = event.target.getBoundingClientRect().left; this.elTop = event.target.getBoundingClientRect().top; } }
此時就獲取到了點擊加入購物車圖標的位置啦:v:這個時候離成功進了一大半~ 獲取到增加購物車圖標的距離后,通過相對位置來確定商品縮略小球的位置,于是在動畫渲染前我們設置下他的 transform
值,x,y的值自己可以調整,并且讓他的透明度為0,暫時不顯示.
beforeEnter (el) { // 設置transform值 el.style.transform = `translate3d(${this.elLeft - 30}px,${this.elTop - 100}px , 0)`; // 設置透明度 el.style.opacity = 0; },
接下來就是關鍵,如何讓小球從當前位置移動到底部 Tabbar
的購物車中呢?同樣的方法,我們通過 getBoundingClientRect
方法來確定底部Tabbar的購物車徽標的 left
和 top
值,獲取到這個值后,就讓小球在當前位置,以貝塞爾曲線的方式向購物車x和y的方向移動,當移動完成后將數組 showMoveDot
的屬性設置為 false
且透明度為1.
在小球繪制完成后的方法中
afterEnter (el) { // 獲取底部購物車徽標 const badgePosition = document .getElementById("buycar") .getBoundingClientRect(); // 設置小球移動的位移 el.style.transform = `translate3d(${badgePosition.left + 30}px,${badgePosition.top - 30}px,0)` // 增加貝塞爾曲線 el.style.transition = 'transform .88s cubic-bezier(0.3, -0.25, 0.7, -0.15)'; el.style.transition = 'transform .88s linear'; this.showMoveDot = this.showMoveDot.map(item => false); // 設置透明度 el.style.opacity = 1; }
此時大功告成!點擊添加購物車按鈕,小球可以曲線飛到購物車中了,來個Gif圖炫耀下✿✿ヽ(°▽°)ノ✿
掘友請留步(╥╯^╰╥)你以為這樣就算完成了嘛~對于Geek:monkey_face:來說,這樣的效果,簡直太Low啦,于是乎,咱們繼續一起來做個優化吧~
優化一:把小球變成點擊當前商品的圖片
剛開始還真TM把我給難住了,這么多圖片,鬼知道顯示哪個呢?后來靈機一動,不就是個動態加載圖片嘛,點擊加入購物車的時候當前的商品對象已經拿到了,你怕啥,直接取就完啦!~so easy:smile:好,思路有了,那咱就上代碼!
1.在data中追加個 dropImage
屬性.
data () { return { showMoveDot: [], //控制下落的小圓點顯示隱藏 elLeft: 0, //當前點擊購物車按鈕在網頁中的絕對top值 elTop: 0, //當前點擊購物車按鈕在網頁中的絕對left值 dropImage: '' // 小球圖片 }
2.在Dom中通過動態綁定的方式來獲取 dropImage
<transition appear @after-appear='afterEnter' @before-appear="beforeEnter" v-for="(item,index) in showMoveDot" :key="index.id"> <div class="move_dot" ref="ball" v-if="item"> <!-- 小球圖片 --> <img :src="dropImage" alt=""> </div> </transition>
3.動態給 dropImage
賦值
addToCart (product) { // 取出商品的圖片 this.dropImage = product.small_image; // 將商品添加到購物車中 this.ADD_TO_CART(product); // 購物車左邊的 this.elLeft = event.target.getBoundingClientRect().left; this.elTop = event.target.getBoundingClientRect().top; this.showMoveDot = [...this.showMoveDot, true]; },
好啦!此時我們就完成了小球圖片的動態加載,來個Gif圖炫一哈✿✿ヽ(°▽°)ノ✿
但是有木有發現個問題,圖片飛過去很突兀,直來直去的,不夠友好,行那咱繼續優化~~
哈哈~讓商品飛入的時候逐漸變小,思來想去,還是用 css3
的 keyframes
來搞比較好,廢話不多說直接上代碼.
1.設置 keyframes
的值
@keyframes mymove { 0% { transform: scale(1); } 25% { transform: scale(0.8); } 50% { transform: scale(0.6); } 75% { transform: scale(0.4); } 100% { transform: scale(0.2); } }
animation
并加入 keyframes
img { animation: 0.88s mymove ease-in-out; width: 3rem; height: 3rem; border-radius: 50%; }
好嘞,搞定!來個Gif圖炫一哈✿✿ヽ(°▽°)ノ✿
為啥我覺得還是有點突兀呢,沒辦法,處女座,必須讓他更完美:see_no_evil:
商品縮略小球逐漸變小的落入到購物車中,此時,購物車再來個彈簧效果就更美了,還是老辦法用 css3
的 keyframes
再合適不過啦~
由于Tabbar是用的 Vant
UI組件,在單獨的 Dashboard.vue
文件中,所以在 Dashboard.vue
文件中給購物車這個圖標設置 keyframes
值.
@keyframes carmove { 0% { transform: scale(1); } 25% { transform: scale(0.8); } 50% { transform: scale(1.1); } 75% { transform: scale(0.9); } 100% { transform: scale(1); } }
并且把這個 keyframes
值設置給購物車這個圖標
.moveToCart { animation: mymove 0.5s ease-in-out; }
購物車的動畫是加完了,但是如何控制小球移入到購物車后讓動畫生效呢?于是先找到小球動畫結束的方法,通過查資料找到了 transitionend
和 webkitAnimationEnd
兩個方法,于是我對他們做了監聽,當小球消失的時候在這兩個方法中動態的增加Tabbar底部購物車的 keyframes
值.
afterEnter (el) { // 監聽小球動畫結束方法 el.addEventListener('transitionend', () => { el.style.display = 'none'; this.listenInCart(); }) // 監聽小球動畫結束方法 el.addEventListener('webkitAnimationEnd', () => { el.style.display = 'none'; this.listenInCart(); }) },
this.listenInCart() 方法是控制底部Tabbar購物車圖標動畫的方法,我們已經定義了一個class moveToCart ,我采用取巧的辦法,當動畫結束的時候,給Tabbar的購物車添加class moveToCart ,然后讓他在500ms后在移除這個class,這樣就會保證每次增加購物車后,底部Tabbar都會執行 keyframs 動畫.
listenInCart () { // 拿到底部Tabbar購物車的DOM元素添加class document.getElementById("buycar").classList.add('moveToCart'); setTimeout(() => { // 500毫秒后移除底部Tabbar購物車的DOM元素class document.getElementById("buycar").classList.remove('moveToCart'); }, 500); }
此時算是真正的大功告成:cherry_blossom:,來個Gif圖炫耀一哈✿✿ヽ(°▽°)ノ✿
都看到這里啦,還不點贊支持下:smile:,鼓勵下作者~ 三、重點來了:rocket::rocket:
我知道掘友們已經迫不及待的想看源碼啦~當然本篇知識點只是整個項目的冰山一角,還有很多好用好玩的新技術,如 Better-scroll 滾動使用,高德地圖的集成,圖片瀑布流,移動端適配等等主流技術在這個項目中幾乎都有~放個GitHub連接,掘友們可不要吝嗇手中的小星星哦✿✿ヽ(°▽°)ノ✿
:tada:Vue構建大型單頁面電商應用 開源啦!點我看源碼:rocket::rocket:
總結
以上所述是小編給大家介紹的Vue實現商品飛入購物車效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。