Vue + AnimeJS實(shí)現(xiàn)3d輪播圖的詳細(xì)代碼
效果如下:
基礎(chǔ)布局
首先需要設(shè)置輪播容器中的子元素位于3D容器中,這是需要設(shè)置transform-style。transform-style有兩個(gè)值,flat:設(shè)置元素的子元素位于該元素的平面中、preserve-3d:設(shè)置元素的子元素位于3D空間中。
與之對(duì)應(yīng)的還需要設(shè)置perspective,指與z=0平面的距離 實(shí)現(xiàn)3d效果的輪播圖主要需要?jiǎng)討B(tài)修改transform中translateX,rotateY,scale以及每個(gè)圖片的層級(jí)、透明度。
由上圖可知,縮放比例、層級(jí)、透明度三個(gè)屬性中間值最大,然后兩邊的值逐級(jí)遞減。在X軸上的偏移值是以中間圖片為基準(zhǔn)向左(逐級(jí)遞減)、向右偏移(逐級(jí)遞增)。Y軸上的旋轉(zhuǎn)以中間圖片為基準(zhǔn)左邊順時(shí)針旋轉(zhuǎn),右邊逆時(shí)針旋轉(zhuǎn)。
這里輪播圖為無限輪播效果,處理方式是在初始化的時(shí)候保存上述五個(gè)參數(shù),因?yàn)樵趺囱h(huán),固定位置對(duì)應(yīng)的五個(gè)參數(shù)是相同的,在切換的時(shí)候就不需要重新計(jì)算。
因?yàn)槭褂玫氖莢ite,獲取靜態(tài)文件資源的時(shí)候需要使用new URL()方法來實(shí)現(xiàn)資源的引用。初始化代碼如下:
<div style="display: flex; align-items: center; justify-content: center"> <el-icon size="30" @click="clickArrow('left')"><ArrowLeft /></el-icon> <div class="carousel-wrapper" ref="carouselRef"> <div v-for="(carousel, index) in carouselList" :key="carousel.id" :data-base-id="carousel.id" class="item" :style="computedStyle(index)" > <img :src="carousel.url" /> </div> </div> <el-icon size="30" @click="clickArrow('right')"><ArrowRight /></el-icon> </div>
const carouselList = ref([ { id: 1, url: new URL('../../assets/images/1.jpg', import.meta.url).href }, { id: 2, url: new URL('../../assets/images/2.jpg', import.meta.url).href }, { id: 3, url: new URL('../../assets/images/3.jpg', import.meta.url).href }, { id: 4, url: new URL('../../assets/images/4.jpg', import.meta.url).href }, { id: 5, url: new URL('../../assets/images/5.jpg', import.meta.url).href } ]) const carouselRef = ref() type CarouseInfo = { x: number[] y: number[] z: number[] opacity: number[] } const carouselInfo = reactive<CarouseInfo>({ x: [], y: [], z: [], opacity: [] }) const baseParams = { x: 150, xOffset: -300, y: -25, yOffset: 50, opacity: 0.6, opacityOffset: 0.2 } const computedStyle = (i: number) => { const { opacity, opacityOffset, xOffset, yOffset } = baseParams let z = 0 let opacityNum = 0 let x = i * baseParams.x + xOffset let y = i * baseParams.y + yOffset const centerIndex = (carouselList.value.length - 1) / 2 if (i <= centerIndex) { z = i * 5 opacityNum = i * opacityOffset + opacity } else { const baseIndex = i - centerIndex * (i - centerIndex) z = baseIndex * 5 opacityNum = baseIndex * opacityOffset + opacity } carouselInfo.x.push(x) carouselInfo.y.push(y) carouselInfo.z.push(z) carouselInfo.opacity.push(opacityNum) return { transform: `translateX(${x}px) rotateY(${y}deg) scale(${opacityNum})`, zIndex: z, opacity: opacityNum } }
.carousel-wrapper { width: 900px; height: 100vh; display: flex; justify-content: center; align-items: center; position: relative; transform-style: preserve-3d; overflow: hidden; perspective: 1000px; } .item { position: absolute; user-select: none; }
輪播
在項(xiàng)目初始化時(shí)保存了初始化參數(shù),點(diǎn)擊左側(cè)按鈕時(shí),分別獲取保存的五個(gè)參數(shù)中的第一個(gè),然后放到數(shù)組中的末尾,點(diǎn)擊右側(cè)按鈕時(shí),分別獲取五個(gè)參數(shù)中的最后一個(gè),放到數(shù)組中的最前面,代碼如下:
const switchPosition = (val: number[], type = 'right') => { const target = type === 'right' ? val.shift() : val.pop() type === 'right' ? val.push(target!) : val.unshift(target!) return val }
為了更好的處理動(dòng)畫,這里使用animejs處理,根據(jù)點(diǎn)擊之后的參數(shù),重新遍歷dom節(jié)點(diǎn),修改每個(gè)dom的偏移值、旋轉(zhuǎn)角度、縮放比例、透明度,因?yàn)闆]有在animejs中找到設(shè)置層級(jí)的屬性,所以這里使用原生設(shè)置層級(jí)。代碼如下:
const clickArrow = (arrowType: string) => { const x = switchPosition(carouselInfo.x, arrowType) const y = switchPosition(carouselInfo.y, arrowType) const z = switchPosition(carouselInfo.z, arrowType) const opacity = switchPosition(carouselInfo.opacity, arrowType) Array.from(carouselRef.value.children).forEach((item, index) => { ;(item as HTMLDivElement).style.zIndex = z[index].toString() anime({ targets: item as HTMLDivElement, translateX: x[index], rotateY: y[index], scale: opacity[index], opacity: opacity[index], easing: 'linear' }) }) }
至此,一個(gè)能夠循環(huán)的3D輪播圖就完成了。代碼示例如下:
https://stackblitz.com/edit/vitejs-vite-1mgsdu?file=src%2Fassets%2Fimages%2F4.jpg
以上就是Vue + AnimeJS實(shí)現(xiàn)3d輪播圖的詳細(xì)代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue AnimeJS3d輪播圖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解vue-router2.0動(dòng)態(tài)路由獲取參數(shù)
本篇文章主要介紹了詳解vue-router2.0動(dòng)態(tài)路由獲取參數(shù),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06Vue.js實(shí)現(xiàn)watch屬性的示例詳解
本文討論了watch函數(shù)是如何利用副作用函數(shù)和options進(jìn)行封裝實(shí)現(xiàn)的,也通過調(diào)度函數(shù)去控制回調(diào)函數(shù)的立即執(zhí)行和執(zhí)行時(shí)機(jī),還可以解決競(jìng)態(tài)問題,感興趣的可以了解一下2022-04-04Vue.js 實(shí)現(xiàn)微信公眾號(hào)菜單編輯器功能(一)
最近vue.js 非?;馃?,小編也趁機(jī)學(xué)習(xí)了下vuejs的一些基礎(chǔ)知識(shí),于是嘗試做一個(gè)像微信平臺(tái)里的菜單編輯器功能,下面腳本之家小編把vue.js 微信公眾號(hào)菜單編輯器功能的實(shí)現(xiàn)代碼分享給大家,需要的朋友參考下2018-05-05vuedraggable實(shí)現(xiàn)簡(jiǎn)單拖拽功能
這篇文章主要為大家詳細(xì)介紹了vuedraggable實(shí)現(xiàn)拖拽功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04vue基于element-ui的三級(jí)CheckBox復(fù)選框功能的實(shí)現(xiàn)代碼
最近vue項(xiàng)目需要用到三級(jí)CheckBox復(fù)選框,需要實(shí)現(xiàn)全選反選不確定三種狀態(tài)。這篇文章主要介紹了vue基于element-ui的三級(jí)CheckBox復(fù)選框功能的實(shí)現(xiàn)方法,需要的朋友可以參考下2018-10-10vue+elementUI-el-table實(shí)現(xiàn)動(dòng)態(tài)顯示隱藏列方式
這篇文章主要介紹了vue+elementUI-el-table實(shí)現(xiàn)動(dòng)態(tài)顯示隱藏列方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01Vue Router動(dòng)態(tài)路由使用方法總結(jié)
這篇文章主要介紹了Vue Router動(dòng)態(tài)路由使用方法總結(jié),需要的朋友可以參考下2023-10-10Vue實(shí)例初始化為渲染函數(shù)設(shè)置檢查源碼剖析
這篇文章主要為大家介紹了Vue實(shí)例初始化為渲染函數(shù)設(shè)置檢查源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08