這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 近期對管理後臺相關功能進行優化,其中導出功能涉及到查詢數據過多導致查詢很慢問題,決定採用點擊後加入到下載中心方式,既解決了介面慢等待問題,也方便後期各種文件的重覆下載,一舉多得~ 功能上很好實現,調介面就可以了,主要涉及到一個小球飛入效果 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
近期對管理後臺相關功能進行優化,其中導出功能涉及到查詢數據過多導致查詢很慢問題,決定採用點擊後加入到下載中心方式,既解決了介面慢等待問題,也方便後期各種文件的重覆下載,一舉多得~
功能上很好實現,調介面就可以了,主要涉及到一個小球飛入效果,基礎原理和商城的加入購物車很像,就是點擊按鈕之後,出現一個小球,按照一定路徑飛入固定位置。先來看下基本的原理圖:
最終效果就是,點擊按鈕,出現小球按照紅色線路徑飛入到下載中心位置。通過原理圖,我們也可以看出。只要知道兩個元素的位置差,然後通過一定屬性控制動畫路徑就可以了,這裡採用了css3的transfrom動畫。
兩個元素的位置差:
獲取位置差x軸:下載中心.left - 按鈕.clientX
獲取位置差y軸:下載中心.top - 按鈕.clientY
其中按鈕的相關屬性,可以在點擊時通過$event
去獲取。
下載中心相關屬性,通過ref?.value?.getBoundingClientRect()
獲取。同時這裡需要註意,因為是在pc端瀏覽器,是可以隨時放大縮小瀏覽器的,在瀏覽器大小變化的時候,下載中心的位置是會發生變化的。因此這裡需要使用window
的resize
方式進行監聽,隨時獲取下載中心的位置,並把相關的top和left值進行存儲,方便後面調用。
css3相關動畫屬性
這個動畫效果里,主要用到了下邊幾個屬性,簡單說一下:
transform:css動畫,對應的值可以是二維動畫(移動、平面旋轉、放大縮小等)、三維動畫(x/y/z三維空間動畫)
translate3d:包含三個參數,分別為x軸移動距離、y軸移動距離、z軸移動距離。
transition-duration:過渡動畫的過渡時間,也就是動畫持續的時間。
transition-timing-function:設置過渡動畫的動畫類型,具體值可以看下圖
示例中使用的是transform3d動畫,相比普通的二維動畫,主要是因為前者可以開啟瀏覽器的gpu硬體加速,能夠快速渲染動畫。
示例代碼
// 小球單獨組件 <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 }, //持續時間 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軸動畫漸入漸出效果 yTimeFunction: ['ease-in', 'ease-out'], // y軸動畫漸入漸出效果 endPos: { x: sessionStorage.getItem('downIconLeft'), // 因為瀏覽器可能會手動放大縮小,所以要監聽window的resize時間,獲取頂部元素位置 y: sessionStorage.getItem('downIconTop') } }; }, mounted() { this.initBalls() }, methods: { // 外部調用方法,傳入點擊時元素的xy位置數值 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)) } // 監聽屏幕變化按鈕位置 window.addEventListener('resize', debounce(()=>{ getIconSite() }), 500) onMounted(()=>{ getIconSite() }) onBeforeUnmount(()=>{ window.removeEventListener('resize') })
// 組件調用 import ball from '@/components/ball/index.vue' <ball ref="cartBtn"></ball> <button @click='download($event)'>下載</button> // 適當方法里調用 download = ()=>{ cartBtn.value.drop({ x: e.clientX, y: e.clientY }) }簡單的小球飛入動畫就完成了,類似的效果可以用到很多地方,不需要太多邏輯代碼,朴實無華效果最靠譜