一个旋转轮播动效

65 阅读1分钟
<template>
  <div class="swiper-wrapper">
    <div class="swiper-box">
      <div v-for="(item, idx) in images" :key="idx" class="swiper-item" :style="getItemStyle(idx)">
        <img :src="item" class="animation-gif" alt="" />
      </div>
    </div>
    <div class="swiper-indicator">
      <SwiperIndicator :count="images.length" :activeIndex="activeIndex" />
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import SwiperIndicator from './SwiperIndicator.vue';
import img1 from '@/pages/home/assets/images/paipai.gif';

const images = [img1, img1, img1];

const activeIndex = ref(0);
let timer = null;

const getItemStyle = (idx) => {
  const total = images.length;
  const diff = (idx - activeIndex.value + total) % total;
  // 0:当前,1:下一个,2:上一个
  let rotateY = 0;
  let zIndex = 1;
  let opacity = 1;
  if (diff === 0) {
    rotateY = 0;
    zIndex = 3;
    opacity = 1;
  } else if (diff === 1) {
    rotateY = 90;
    zIndex = 2;
    opacity = 0.5;
  } else if (diff === 2) {
    rotateY = -90;
    zIndex = 2;
    opacity = 0.5;
  }
  return {
    transform: `rotateY(${rotateY}deg) translateZ(120px)`,
    zIndex,
    opacity,
    transition: 'transform 0.8s cubic-bezier(0.4,0.2,0.2,1), opacity 0.8s',
    position: 'absolute',
    top: 0,
    left: 0,
    width: '100%',
    height: '100%',
    backfaceVisibility: 'hidden',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
  };
};

const next = () => {
  activeIndex.value = (activeIndex.value + 1) % images.length;
};

onMounted(() => {
  timer = setInterval(next, 8000);
});

onBeforeUnmount(() => {
  if (timer) clearInterval(timer);
});
</script>

<style lang="scss" scoped>
.swiper-wrapper {
  background-image: url('@/pages/home/assets/images/left-bg.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  width: 510px;
  height: 302.102px;
  margin-left: 86px;
  transform: translateY(100px);
  position: relative;
  .swiper-box {
    width: 100%;
    height: 100%;
    position: relative;
    perspective: 800px;
    transform-style: preserve-3d;
  }
  .swiper-item {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    will-change: transform, opacity;
  }
  .animation-gif {
    width: 100%;
    height: 100%;
    object-fit: contain;
    // transform: translateX(-8px) translateY(-19px);
  }
}
</style>