You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue JS 3图片淡入过渡动画失效,如何正确实现?

Vue 3图片淡入过渡失效的解决办法

问题场景

实现图片加载时显示旋转动画,加载完成后动画淡出、图片淡入的效果。目前旋转动画的淡出正常,但图片直接渲染无过渡效果,替换为文本块则过渡正常。

原代码

图片组件代码

<script setup>
  import FadeTransition from '../transitions/fade-transition.vue';
  import { reactive } from 'vue'

  const props = defineProps({
    imgUrl: String,
    route: String
  })

  let getURL = function () {
    return new URL(props.imgUrl, import.meta.url);
  }

  let show = reactive({showing: false});
  let showImg = function () {
    show.showing = true;
  }
</script>

<template>
  <div class="frame">
    <FadeTransition><div v-show="!show.showing" class="loader"></div></FadeTransition>
    <RouterLink :to="props.route"><FadeTransition><img v-show="show.showing" class="image" :src="getURL()" @load="showImg()"/></FadeTransition></RouterLink>
  </div>
</template>

<style scoped>
  .frame {
    width: 33.3333%;
    aspect-ratio: 1/1;
    margin: 0px;
    display: inline-flex;
    position: relative;
    padding: 6px;
  }

  .image {
    width: calc(100% - 12px);
    height: calc(100% - 12px);
    position: absolute;
  }

  .loader {
    border: 4px solid var(--grey);
    border-top: 4px solid var(--darkGrey);
    border-radius: 50%;
    width: 30px;
    height: 30px;
    animation: spin 5s linear infinite;
    position: absolute;
    left: calc(50% - 15px);
    top: calc(50% - 15px);
  }

  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
</style>

FadeTransition组件代码

<script>
</script>

<template>
  <Transition name="fade">
    <slot></slot> 
  </Transition>
</template>

<style>
  .fade-enter-active, 
  .fade-leave-active {
    transition: opacity 0.5s ease;
  }

  .fade-enter-from, 
  .fade-leave-to {
    opacity: 0;
  }
</style>

问题原因

原代码使用v-show控制图片显示,v-show仅切换元素的display属性,图片始终存在于DOM中。当图片加载完成触发@load事件时,图片已经渲染完成,此时设置show.showing = true,浏览器直接显示图片,Vue的Transition无法捕捉到元素从无到有的插入动作,因此淡入过渡不生效。而文本块因为内容简单,状态变化时过渡能正常触发,但图片因已加载完成,浏览器会直接绘制跳过过渡。

解决方案

改用预加载图片 + v-if控制DOM插入的方式,确保图片加载完成后才插入DOM,让Transition能捕捉到元素插入动作,触发淡入过渡。

修改后的图片组件代码

<script setup>
import FadeTransition from '../transitions/fade-transition.vue';
import { ref, onMounted } from 'vue'

const props = defineProps({
  imgUrl: String,
  route: String
})

// 生成图片URL
const getURL = () => new URL(props.imgUrl, import.meta.url);

// 控制加载器和图片的显示状态
const isImageLoaded = ref(false);
const showLoader = ref(true);

onMounted(() => {
  // 预加载图片,避免插入DOM时才开始加载
  const preloadImg = new Image();
  preloadImg.src = getURL();
  preloadImg.onload = () => {
    // 先隐藏加载器(触发淡出)
    showLoader.value = false;
    // 触发图片插入DOM(触发淡入)
    isImageLoaded.value = true;
  }
})
</script>

<template>
  <div class="frame">
    <FadeTransition>
      <!-- 用v-if控制加载器的DOM存在状态 -->
      <div v-if="showLoader" class="loader"></div>
    </FadeTransition>
    <RouterLink :to="props.route">
      <FadeTransition>
        <!-- 图片加载完成后才插入DOM,触发淡入过渡 -->
        <img v-if="isImageLoaded" class="image" :src="getURL()" />
      </FadeTransition>
    </RouterLink>
  </div>
</template>

<!-- 样式部分保持不变 -->
<style scoped>
  .frame {
    width: 33.3333%;
    aspect-ratio: 1/1;
    margin: 0px;
    display: inline-flex;
    position: relative;
    padding: 6px;
  }

  .image {
    width: calc(100% - 12px);
    height: calc(100% - 12px);
    position: absolute;
  }

  .loader {
    border: 4px solid var(--grey);
    border-top: 4px solid var(--darkGrey);
    border-radius: 50%;
    width: 30px;
    height: 30px;
    animation: spin 5s linear infinite;
    position: absolute;
    left: calc(50% - 15px);
    top: calc(50% - 15px);
  }

  @keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
  }
</style>

FadeTransition组件无需修改

保留原FadeTransition组件的代码即可,它会为插入DOM的元素正确应用淡入淡出过渡。

额外说明

如果希望加载器淡出和图片淡入更连贯,可以在设置isImageLoaded.value = true前添加一小段延迟(比如10ms),确保加载器的淡出过渡先触发:

preloadImg.onload = () => {
  showLoader.value = false;
  setTimeout(() => {
    isImageLoaded.value = true;
  }, 10);
}

内容的提问来源于stack exchange,提问作者jban28

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 13:52:07