类似轮播图不过不会主动切换,因为需求仅展示三张图片,如需多张图片切换需要自己拓展,直接上代码
3d图片切换
index.vue
<template>
<div class="main">
<div class="rotation">
<div :class="contentList.one.class">
<p>{{ contentList.one.data }}</p>
<img :src="require('@/assets/images/longImage.jpg')" />
</div>
<div :class="contentList.two.class">
<p>{{ contentList.two.data }}</p>
<img :src="require('@/assets/images/longImage.jpg')" />
</div>
<div :class="contentList.three.class">
<p>{{ contentList.three.data }}</p>
<img :src="require('@/assets/images/longImage.jpg')" />
</div>
<div :class="contentList.hide.class">
<p>{{ contentList.hide.data }}</p>
<img :src="require('@/assets/images/longImage.jpg')" />
</div>
</div>
</div>
<el-button @click="change('one')">0</el-button>
<el-button @click="change('two')">1</el-button>
<el-button @click="change('three')">2</el-button>
</template>
<script lang="ts" setup>
import { nextTick, reactive } from "vue";
let hideDirection = "";
let classList = reactive([
{ name: "one", realityInfo: "one" },
{ name: "two", realityInfo: "two" },
{ name: "three", realityInfo: "three" },
{ name: "hide", realityInfo: "hide" },
]);
let activeName = "";
let contentList: any = reactive({
one: {
data: 0,
class: ["left"],
},
two: {
data: 1,
class: [],
},
three: {
data: 2,
class: ["right"],
},
hide: {
data: 3,
class: ["hide"],
},
});
const change = (dataName: string) => {
if (activeName === dataName) {
return;
}
// 当前选中
activeName = dataName;
// 需删除索引
let deleteIndex = classList.length - 1;
// 会被替换上的元素
let replaceName = classList[deleteIndex].name;
if (hideDirection === "left") {
deleteIndex = 0;
replaceName = classList[deleteIndex].name;
}
// 删除要替换的
classList.splice(deleteIndex, 1);
// 要选中得数据索引
let dataIndex = getInfoIndex(dataName);
// 为0表示替换元素需要从左侧出现到右侧
if (dataIndex === 0) {
// 需要把移动后隐藏的数据替换到要替换出现的元素上(replaceName)
let deleteName = classList[classList.length - 1].name;
// 记录实际信息
let deleteRealityName = classList[classList.length - 1].realityInfo;
// 替换数据
contentList[replaceName].data = contentList[deleteName].data;
// 隐藏的真实数据设置为隐藏
classList[classList.length - 1].realityInfo = "hide";
// 插入在最前面,因为要从左侧出现
classList.unshift({
name: replaceName,
realityInfo: deleteRealityName,
});
nextTick(() => {
hideDirection = "right";
setStyle("right");
});
} else if (dataIndex === 2) {
// 需要把移动后隐藏的数据替换到要替换出现的元素上(replaceName)
contentList[replaceName].data = contentList[classList[0].name].data;
// 记录实际信息
let deleteRealityName = classList[0].realityInfo;
// 隐藏的真实数据设置为隐藏
classList[0].realityInfo = "hide";
// 插入在最后面,因为要从右侧出现
classList.push({
name: replaceName,
realityInfo: deleteRealityName,
});
nextTick(() => {
hideDirection = "left";
setStyle("left");
});
}
};
/**
* 获得数据实际所在位置
* @param dataName
*/
const getInfoIndex = (dataName: string) => {
for (let index = 0; index < classList.length; index++) {
const item = classList[index];
if (item.realityInfo === dataName) {
return index;
}
}
};
/**
* 设置样式
* @param leftOrRight
*/
const setStyle = (leftOrRight: string) => {
if (leftOrRight === "right") {
contentList[classList[0].name].class.length = 0;
contentList[classList[0].name].class = ["right1"];
contentList[classList[1].name].class = ["right2"];
contentList[classList[2].name].class = ["right3"];
contentList[classList[3].name].class = ["right4"];
} else {
contentList[classList[0].name].class = ["left1"];
contentList[classList[1].name].class = ["left2"];
contentList[classList[2].name].class = ["left3"];
contentList[classList[3].name].class = ["left4"];
}
};
</script>
<style lang="scss">
@import "./test.scss";
</style>
test.scss
```css
.main {
margin: 0;
padding: 0;
/* 设置flex布局 */
display: flex;
/* 在主轴上居中 */
justify-content: center;
/* 在测轴上居中 */
align-items: center;
height: 100vh;
}
.rotation {
height: 600px;
width: 1000px;
overflow: hidden;
margin: 0 auto;
position: relative;
perspective: 754px;
transform-style: preserve-3d;
div {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
/* 图片居中 */
text-align: center;
img {
width: 300px;
}
}
.hide {
transform: rotateY(-20deg) translateZ(-40px) translateX(-910px);
}
.hideMove {
animation: dh 1s;
animation-fill-mode: forwards;
}
.left {
transform: rotateY(-10deg) translateZ(-40px) translateX(-360px);
// display: none;
// animation: dh2 1s;
// animation-fill-mode: forwards;
}
.leftMove {
animation: dh2 1s forwards;
}
.center {
// animation: dh3 1s;
// animation-fill-mode: forwards;
// transform: rotateY(-10deg) translateZ(-40px);
}
.conterMove {
animation: dh3 1s forwards;
}
.right {
transform: rotateY(10deg) translateZ(-40px) translateX(360px);
}
.rightMove {
animation: dh4 1s forwards;
}
}
.left1 {
animation: left1 1s forwards;
}
.left2 {
animation: left2 1s forwards;
}
.left3 {
animation: left3 1s forwards;
}
.left4 {
animation: left4 1s forwards;
}
.right1 {
animation: dh 1s forwards;
}
.right2 {
animation: dh2 1s forwards;
}
.right3 {
animation: dh3 1s forwards;
}
.right4 {
animation: dh4 1s forwards;
}
/* 整体旋转动画 */
@keyframes left1 {
from {
transform: rotateY(-10deg) translateZ(-40px) translateX(-360px);
}
to {
transform: rotateY(-20deg) translateZ(-40px) translateX(-920px);
}
}
/* 整体旋转动画 */
@keyframes left2 {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(-10deg) translateZ(-40px) translateX(-360px);
}
}
/* 整体旋转动画 */
@keyframes left3 {
from {
transform: rotateY(10deg) translateZ(-40px) translateX(360px);
}
to {
transform: rotateY(0deg);
}
}
/* 整体旋转动画 */
@keyframes left4 {
from {
transform: rotateY(20deg) translateZ(-40px) translateX(920px);
}
to {
transform: rotateY(10deg) translateZ(-40px) translateX(360px);
}
}
/* 整体旋转动画 */
@keyframes dh {
from {
transform: rotateY(-20deg) translateZ(-40px) translateX(-920px);
}
to {
transform: rotateY(-10deg) translateZ(-40px) translateX(-360px);
}
}
@keyframes dh2 {
from {
transform: rotateY(-10deg) translateZ(-40px) translateX(-360px);
}
to {
transform: rotateY(0deg);
}
}
@keyframes dh3 {
from {
transform: rotateY(0deg);
}
to {
transform: rotateY(10deg) translateZ(-40px) translateX(360px);
}
}
@keyframes dh4 {
from {
transform: rotateY(10deg) translateZ(-40px) translateX(360px);
}
to {
transform: rotateY(20deg) translateZ(-40px) translateX(920px);
}
}