typeScript vue3 3D图片切换

类似轮播图不过不会主动切换,因为需求仅展示三张图片,如需多张图片切换需要自己拓展,直接上代码

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);
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值