首页 > 解决方案 > CSS/Vue.js 将动画重置与 ref 值更改同步

问题描述

我想创建一个在 3 个状态之间渐变的动画。为了存储这些状态(包含图像和一些文本),我创建了一个对象数组 ( uploadSteps)。我以特定的时间间隔增加这个数组的索引来创建动画。

我的问题来自CSS,我想在每一步之间创建一个淡出/淡入效果,以便过渡更平滑。它大部分时间都有效,但有时,在刷新和第一次转换之后,我认为 CSS 动画在状态改变之前重新启动。到目前为止,我无法不断地复制它。

它的作用=> 图像淡入 -> 图像 1 -> 图像 1 淡出 -> 图像 1 -> 图像 2 淡入

我想要的 => 图像淡入 -> 图像 1 -> 图像 1 淡出 -> 图像 2 淡入

如果你注意,你会看到在图像 1 和 2 之间的过渡处有一种闪烁效果。我能做些什么来解决这个问题?帮助表示赞赏!

PS:我已经包含了一些视频来说明我的问题

https://streamable.com/4aigjq - 动画KO

https://streamable.com/umu3nj - 动画OK

<template>
  <div class="screenshot-upload-processing-container">
    <div class="image-container">
      <img
        ref="imageRef"
        :src="
          currentStep ? $requireImage(currentStep.imagePath).toString() : ''
        "
        :alt="currentStep.text"
        class="image"
      />
    </div>
    <div class="centered-row">
      <span ref="textRef" class="text">{{
        currentStep ? currentStep.text : ''
      }}</span>
    </div>
  </div>
</template>

<script lang="ts">
import {
  computed,
  defineComponent,
  onBeforeUnmount,
  ref,
} from '@nuxtjs/composition-api';

export default defineComponent({
  name: 'ScreenshotUploadProcessing',
  setup() {
    const stepNumber = ref(0);
    const timer = ref<NodeJS.Timeout | null>(null);
    const imageRef = ref<HTMLImageElement | null>(null);
    const textRef = ref<HTMLSpanElement | null>(null);

    const uploadSteps = computed(() => {    
      return [
        {
          imagePath: 'image1.svg',
          text: 'Text 1',
        },
        {
          imagePath: 'image2.svg',
          text: 'Text 2',
        },
        {
          imagePath: 'image3.svg',
          text: 'Text 3',
        },
      ];
    });

    const resetAnimations = () => {
      const image = imageRef.value;
      const text = textRef.value;

      if (image) {
        image.style.animation = 'none';
        void image.offsetHeight;
        image.style.animation = '';
      }
      if (text) {
        text.style.animation = 'none';
        void text.offsetHeight;
        text.style.animation = '';
      }
    };

    const updateStepNumber = () => {
      timer.value = setInterval(() => {
        if (stepNumber.value === uploadSteps.value.length - 1) {
          stepNumber.value = 0;
        } else {
          stepNumber.value++;
        }

        resetAnimations();
      }, 3000);
    };

    onBeforeUnmount(() => {
      clearInterval(timer.value as NodeJS.Timeout);
    });

    const currentStep = computed(() => uploadSteps.value[stepNumber.value]);
    
    updateStepNumber();

    return {
      stepNumber,
      currentStep,
      imageRef,
      textRef,
      uploadSteps,
    };
  },
});
</script>

<style lang="scss" scoped>
@keyframes fade {
  0%,
  100% {
    opacity: 0;
  }

  40%,
  60% {
    opacity: 1;
  }
}

.screenshot-upload-processing-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.image {
  animation: fade 3s linear;
}

.image-container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 27rem;
  margin-top: 10.3rem;
}

.centered-row {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: $spacing-xl;
}

.text {
  @extend %text-gradient-1;

  animation: fade 3s linear;
  font-weight: $font-weight-medium;
}
</style>

标签: cssvue.jsnuxt.jscss-animationsvue-composition-api

解决方案


推荐阅读