各位掘友,很久不見,最近利用工做之餘開源了Vue電商項目,高仿某知名O2O買菜平臺,整個項目作下來收穫仍是蠻多的,能夠掃描下方二維碼體驗,本篇是項目的核心知識拆解篇,主要是拆解增長商品飛入購物車的實現過程。css
點我體驗前端
首先我先簡單的介紹下本項目所用到的技術棧:ios
整個項目採用vue-cli3腳手架搭建,Vue全家桶(vue、vuex、vue-router)、Vant UI框架以及不少著名好用的第三方庫如:axios、fastclick、better-scroll、twix.js、pubsub.js、moment.js、vue-amap等等。 像素單位選擇rem,後臺數據接口經過Easy-Mock搭建,以最接近企業開發的方式,組件化模塊化,最大程度實現高內聚低耦合,大大提高各模塊的可維護及可擴展性,相信讀完源碼和我寫的系列拆解文章,不管你是哪一個段位的攻城獅都會有所啓發!開源不易,你的點贊就是對我最大的鼓勵🎉🎉感謝~Thanks♪(・ω・)ノcss3
首先先來瞅瞅要作成的樣子,是否是很炫酷✈️✈️隨手點贊支持下做者💓git
首先咱們先來把關注點放到加入購物車這塊,當咱們點擊購物車圖標的時候,這個時候會在當前點擊的商品圖片的中央範圍先出現個圓形的商品縮略圖,其次這個商品縮略圖會沿着當前位置以曲線的形式逐漸變小飛入到購物車裏,當商品飛入到購物車時,購物車的數字圖標會增長,同時購物車會出現彈簧動畫。github
經過上面大白話分析整個實現步驟可簡短分爲三個階段來完成編碼:web
第一階段編碼:繪製一個圓形的小球到商品的中間區域 這個很是簡單,就是在商品圖片區域加一個div
,設置position:fixed
及寬度高度等,可是呢?面試
先埋個問題,如何讓小球出如今點擊當前商品的範圍內呢?vue-router
起初我經過計算屬性遍歷了商品列表,在全部的商品視圖中加入商品縮略圖小球,而後,經過給每一個商品列表裏增長一個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,這個方法返回的是一組矩形的集合,這下就好啦,能夠經過這個方法來定位某個元素在屏幕中的位置啦😊~
那好,那咱們這個時候就成熱打鐵,經過這個方法先來肯定點擊購物車圖標的時候,購物車這個小圖標距左邊和頂部相對屏幕的距離。
定義兩個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;
}
}
複製代碼
此時就獲取到了點擊加入購物車圖標的位置啦✌️這個時候離成功進了一大半~ 獲取到增長購物車圖標的距離後,經過相對位置來肯定商品縮略小球的位置,因而在動畫渲染前咱們設置下他的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🐵來講,這樣的效果,簡直太Low啦,因而乎,我們繼續一塊兒來作個優化吧~
剛開始還真TM把我給難住了,這麼多圖片,鬼知道顯示哪一個呢?後來靈機一動,不就是個動態加載圖片嘛,點擊加入購物車的時候當前的商品對象已經拿到了,你怕啥,直接取就完啦!~so easy😄好,思路有了,那咱就上代碼!
dropImage
屬性.data () {
return {
showMoveDot: [], //控制下落的小圓點顯示隱藏
elLeft: 0, //當前點擊購物車按鈕在網頁中的絕對top值
elTop: 0, //當前點擊購物車按鈕在網頁中的絕對left值
dropImage: '' // 小球圖片
}
複製代碼
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>
複製代碼
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
來搞比較好,廢話很少說直接上代碼.
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圖炫一哈✿✿ヽ(°▽°)ノ✿
爲啥我以爲仍是有點突兀呢,沒辦法,處女座,必須讓他更完美🙈
商品縮略小球逐漸變小的落入到購物車中,此時,購物車再來個彈簧效果就更美了,仍是老辦法用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購物車圖標動畫的方法,咱們已經定義了一個classmoveToCart
,我採用取巧的辦法,當動畫結束的時候,給Tabbar的購物車添加classmoveToCart
,而後讓他在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);
}
複製代碼
此時算是真正的大功告成🌸,來個Gif圖炫耀一哈✿✿ヽ(°▽°)ノ✿
都看到這裏啦,還不點贊支持下😄,鼓勵下做者~
我知道掘友們已經火燒眉毛的想看源碼啦~固然本篇知識點只是整個項目的冰山一角,還有不少好用好玩的新技術,如Better-scroll
滾動使用,高德地圖的集成,圖片瀑布流,移動端適配等等主流技術在這個項目中幾乎都有~放個GitHub鏈接,掘友們可不要吝嗇手中的小星星哦✿✿ヽ(°▽°)ノ✿
但願個人逗B式分享能幫助到你,傳播知識,分享快樂,與你一塊兒共同進步~
最近在準備和一個大廠會日語的小姐姐合做把我擱置好久的公衆號:前端甜甜圈搞起來,內容呢,確定是技術相關的,不會瞎扯淡😄初步設想會經過語音加文字的形式,我負責文字,她負責語音,每週2-3次推送,內容涵蓋前端基礎,進階,面試等~目前已經敲定了這位小姐姐的合做,音質沒的說,相信聽完他的每週語音分享,對枯燥乏味的知識將會變得更加有趣和好玩,目前還在緊張有序的籌備中,能夠掃描下方的二維碼先關注下,也能夠掃描個人私人微信拉你進羣,羣裏有資深前端大佬,會不按期分享前端領域好玩有趣有用的新知識~~