JavaScript模擬實(shí)現(xiàn)加入購(gòu)物車飛入動(dòng)畫(huà)效果
近期對(duì)管理后臺(tái)相關(guān)功能進(jìn)行優(yōu)化,其中導(dǎo)出功能涉及到查詢數(shù)據(jù)過(guò)多導(dǎo)致查詢很慢問(wèn)題,決定采用點(diǎn)擊后加入到下載中心方式,既解決了接口慢等待問(wèn)題,也方便后期各種文件的重復(fù)下載,一舉多得~
功能上很好實(shí)現(xiàn),調(diào)接口就可以了,主要涉及到一個(gè)小球飛入效果,基礎(chǔ)原理和商城的加入購(gòu)物車很像,就是點(diǎn)擊按鈕之后,出現(xiàn)一個(gè)小球,按照一定路徑飛入固定位置。先來(lái)看下基本的原理圖:
最終效果就是,點(diǎn)擊按鈕,出現(xiàn)小球按照紅色線路徑飛入到下載中心位置。通過(guò)原理圖,我們也可以看出。只要知道兩個(gè)元素的位置差,然后通過(guò)一定屬性控制動(dòng)畫(huà)路徑就可以了,這里采用了css3的transfrom動(dòng)畫(huà)。
兩個(gè)元素的位置差
獲取位置差x軸:下載中心.left - 按鈕.clientX
獲取位置差y軸:下載中心.top - 按鈕.clientY
其中按鈕的相關(guān)屬性,可以在點(diǎn)擊時(shí)通過(guò)$event
去獲取。
下載中心相關(guān)屬性,通過(guò)ref?.value?.getBoundingClientRect()
獲取。同時(shí)這里需要注意,因?yàn)槭窃趐c端瀏覽器,是可以隨時(shí)放大縮小瀏覽器的,在瀏覽器大小變化的時(shí)候,下載中心的位置是會(huì)發(fā)生變化的。因此這里需要使用window
的resize
方式進(jìn)行監(jiān)聽(tīng),隨時(shí)獲取下載中心的位置,并把相關(guān)的top和left值進(jìn)行存儲(chǔ),方便后面調(diào)用。
css3相關(guān)動(dòng)畫(huà)屬性
這個(gè)動(dòng)畫(huà)效果里,主要用到了下邊幾個(gè)屬性,簡(jiǎn)單說(shuō)一下:
transform:css動(dòng)畫(huà),對(duì)應(yīng)的值可以是二維動(dòng)畫(huà)(移動(dòng)、平面旋轉(zhuǎn)、放大縮小等)、三維動(dòng)畫(huà)(x/y/z三維空間動(dòng)畫(huà))
translate3d:包含三個(gè)參數(shù),分別為x軸移動(dòng)距離、y軸移動(dòng)距離、z軸移動(dòng)距離。
transition-duration:過(guò)渡動(dòng)畫(huà)的過(guò)渡時(shí)間,也就是動(dòng)畫(huà)持續(xù)的時(shí)間。
transition-timing-function:設(shè)置過(guò)渡動(dòng)畫(huà)的動(dòng)畫(huà)類型,具體值可以看下圖
示例中使用的是transform3d動(dòng)畫(huà),相比普通的二維動(dòng)畫(huà),主要是因?yàn)榍罢呖梢蚤_(kāi)啟瀏覽器的gpu硬件加速,能夠快速渲染動(dòng)畫(huà)。
示例代碼
// 小球單獨(dú)組件 <div class="ball-wrap" v-for="(item, k) of balls" :key="k" :style="{ opacity: item.show, top: item.start.y + 'px', left: item.start.x + 'px', transitionDuration: (item.show ? (duration/1000) : 0)+'s', 'transition-timing-function': xTimeFunction[!item.ani ? 0 : 1], transform: 'translate3d(' + item.offset.x + 'px, 0, 0)', zIndex }" > <div class="ball" :class="{ball3d:is3dSheet}" :style="{ marginLeft: -size/2 + 'px', marginTop: -size/2 + 'px', padding: size + 'px', backgroundImage: ballImage, backgroundColor: ballColor, transitionDuration: (item.show ? (duration/1000) : 0) + 's', transform: 'translate3d(0,' + item.offset.y + 'px,0)', 'transition-timing-function': yTimeFunction[item.ani ? 0 : 1] }" ></div> </div> <script> export default { props: { // 球的大小 size: { type: Number, default: 8 }, //3D is3dSheet: { type: Boolean, default: true }, //持續(xù)時(shí)間 duration: { type: Number, default: 800 }, zIndex: { type: Number, default: 9999 }, ballImage: { type: String, default: '' }, ballColor: { type: String, default: '#409eff' } }, data() { return { balls: [], xTimeFunction: ['ease-in', 'ease-out'], // x軸動(dòng)畫(huà)漸入漸出效果 yTimeFunction: ['ease-in', 'ease-out'], // y軸動(dòng)畫(huà)漸入漸出效果 endPos: { x: sessionStorage.getItem('downIconLeft'), // 因?yàn)闉g覽器可能會(huì)手動(dòng)放大縮小,所以要監(jiān)聽(tīng)window的resize時(shí)間,獲取頂部元素位置 y: sessionStorage.getItem('downIconTop') } }; }, mounted() { this.initBalls() }, methods: { // 外部調(diào)用方法,傳入點(diǎn)擊時(shí)元素的xy位置數(shù)值 drop(pos){ this.endPos.x = sessionStorage.getItem('downIconLeft') this.endPos.y = sessionStorage.getItem('downIconTop') let ball let duration=this.duration for (var i = 0; i < this.balls.length; i++) { if(this.balls[i].show){continue} ball = this.balls[i] } ball.start.x = pos.x ball.start.y = pos.y ball.offset.x = this.endPos.x - pos.x ball.offset.y = this.endPos.y - pos.y if(ball.offset.y > 0){ ball.ani = 1 }else{ ball.ani = 0 } ball.show = 1 setTimeout(()=>{ ball.show = 0 }, duration) debounce(this.initBalls, duration+200, this)() }, initBalls(){ const balls = [{ show: 0, start: { x: 0, y: 0 }, offset: { x: 0, y: 0 }, ani: 0 }] this.balls = balls } } } </script>
// 下載中心 <span class="export_center_icon" ref="downRef">下載中心</span> // 獲取下載按鈕位置 const getIconSite = ()=>{ let downIconSite = downRef?.value?.getBoundingClientRect() sessionStorage.setItem('downIconLeft', downIconSite.left.toFixed(2)) sessionStorage.setItem('downIconTop', downIconSite.top.toFixed(2)) } // 監(jiān)聽(tīng)屏幕變化按鈕位置 window.addEventListener('resize', debounce(()=>{ getIconSite() }), 500) onMounted(()=>{ getIconSite() }) onBeforeUnmount(()=>{ window.removeEventListener('resize') })
// 組件調(diào)用 import ball from '@/components/ball/index.vue' <ball ref="cartBtn"></ball> <button @click='download($event)'>下載</button> // 適當(dāng)方法里調(diào)用 download = ()=>{ cartBtn.value.drop({ x: e.clientX, y: e.clientY }) }
簡(jiǎn)單的小球飛入動(dòng)畫(huà)就完成了,類似的效果可以用到很多地方,不需要太多邏輯代碼,樸實(shí)無(wú)華效果最靠譜
以上就是JavaScript模擬實(shí)現(xiàn)加入購(gòu)物車飛入動(dòng)畫(huà)效果的詳細(xì)內(nèi)容,更多關(guān)于JavaScript購(gòu)物車飛入動(dòng)畫(huà)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序?qū)崿F(xiàn)多行文字超出部分省略號(hào)顯示功能
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)多行文字 超出部分省略號(hào)顯示功能,比如設(shè)置只顯示2行,超出部分省略號(hào)顯示,本文通過(guò)實(shí)例代碼給大家介紹,需要的朋友可以參考下2019-10-10js簡(jiǎn)單正則驗(yàn)證漢字英文及下劃線的方法
這篇文章主要介紹了js簡(jiǎn)單正則驗(yàn)證漢字英文及下劃線的方法,結(jié)合完整實(shí)例形式分析了javascript針對(duì)中英文字母與下劃線的正則驗(yàn)證方法,需要的朋友可以參考下2016-11-11javascript字母大小寫(xiě)轉(zhuǎn)換的4個(gè)函數(shù)詳解
這篇文章主要介紹了javascript字母大小寫(xiě)轉(zhuǎn)換的4個(gè)函數(shù)詳解,需要的朋友可以參考下2014-05-05elementui-樹(shù)形控件實(shí)現(xiàn)子節(jié)點(diǎn)右側(cè)添加圖標(biāo)和數(shù)據(jù)鼠標(biāo)放上去顯示文字效果
這篇文章主要介紹了elementui-樹(shù)形控件實(shí)現(xiàn)子節(jié)點(diǎn)右側(cè)添加圖標(biāo)和數(shù)據(jù)鼠標(biāo)放上去顯示文字效果,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-01-01js實(shí)現(xiàn)簡(jiǎn)單的手風(fēng)琴效果
本文主要介紹了js實(shí)現(xiàn)簡(jiǎn)單手風(fēng)琴效果的實(shí)例,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02WebGIS開(kāi)發(fā)中不同坐標(biāo)系坐標(biāo)轉(zhuǎn)換問(wèn)題解決基本步驟
這篇文章主要介紹了如何在JavaScript中使用proj4庫(kù)進(jìn)行坐標(biāo)系轉(zhuǎn)換的基本步驟,包括安裝、示例、自定義坐標(biāo)系定義、擴(kuò)展以及一些常見(jiàn)EPSG代碼對(duì)照表,需要的朋友可以參考下2025-01-01