Vue + AnimeJS实现3d轮播图的详细代码
作者:Kakarotto
效果如下:
基础布局
首先需要设置轮播容器中的子元素位于3D容器中,这是需要设置transform-style。transform-style有两个值,flat:设置元素的子元素位于该元素的平面中、preserve-3d:设置元素的子元素位于3D空间中。
与之对应的还需要设置perspective,指与z=0平面的距离 实现3d效果的轮播图主要需要动态修改transform中translateX,rotateY,scale以及每个图片的层级、透明度。
由上图可知,缩放比例、层级、透明度三个属性中间值最大,然后两边的值逐级递减。在X轴上的偏移值是以中间图片为基准向左(逐级递减)、向右偏移(逐级递增)。Y轴上的旋转以中间图片为基准左边顺时针旋转,右边逆时针旋转。
这里轮播图为无限轮播效果,处理方式是在初始化的时候保存上述五个参数,因为怎么循环,固定位置对应的五个参数是相同的,在切换的时候就不需要重新计算。
因为使用的是vite,获取静态文件资源的时候需要使用new URL()方法来实现资源的引用。初始化代码如下:
<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; }
轮播
在项目初始化时保存了初始化参数,点击左侧按钮时,分别获取保存的五个参数中的第一个,然后放到数组中的末尾,点击右侧按钮时,分别获取五个参数中的最后一个,放到数组中的最前面,代码如下:
const switchPosition = (val: number[], type = 'right') => { const target = type === 'right' ? val.shift() : val.pop() type === 'right' ? val.push(target!) : val.unshift(target!) return val }
为了更好的处理动画,这里使用animejs处理,根据点击之后的参数,重新遍历dom节点,修改每个dom的偏移值、旋转角度、缩放比例、透明度,因为没有在animejs中找到设置层级的属性,所以这里使用原生设置层级。代码如下:
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' }) }) }
至此,一个能够循环的3D轮播图就完成了。代码示例如下:
https://stackblitz.com/edit/vitejs-vite-1mgsdu?file=src%2Fassets%2Fimages%2F4.jpg
以上就是Vue + AnimeJS实现3d轮播图的详细代码的详细内容,更多关于Vue AnimeJS3d轮播图的资料请关注脚本之家其它相关文章!