最轻量可靠的图片淡入淡出方案是用包裹图片并配合css opacity过渡。它无需动画库或uni.createanimation,三端兼容;后者适合复杂动画,但用于简单透明度切换反而冗余且易引发渲染抖动。

直接用 <transition></transition> 包裹图片,配合 CSS 的 opacity 过渡,是最轻量、最可靠的方式。不需要额外引入动画库,也不依赖 uni.createAnimation,H5、小程序、App 三端都支持。
为什么不用 uni.createAnimation 做淡入淡出
uni.createAnimation 适合需要精确控制逐帧变化的复杂动画(比如弹跳、路径运动),但淡入淡出本质只是 opacity 状态切换,用它反而多出 step()、export()、赋值到 animation 属性等冗余步骤。实测在小程序中频繁调用 animation.opacity() + step() 容易触发渲染抖动,尤其列表内多个图同时动画时。
- opacity 变化本身是 CSS 合成层属性,浏览器/小程序原生优化好,硬件加速自动生效
-
uni.createAnimation最终也是转成 style 写入,绕路还损失可读性 - 过渡类名命名和样式复用更方便,比如统一用
.fade类控制所有淡入淡出场景
<transition></transition> 的 class 名必须严格匹配
Vue 的 <transition></transition> 不会自动识别你写的任意 class 名,它靠 name 属性生成固定前缀。比如写 <transition name="fade"></transition>,就必须定义以下三个类:
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
漏掉任意一个,动画就失效——常见错误是只写了 -active,忘了 -enter 和 -leave-to;或者把 fade-enter 写成 fade-enter-from(那是 Vue 3 的写法,uni-app 当前主版本仍基于 Vue 2)。
- 不要用
fade-enter-from或fade-leave,uni-app 不识别 - duration 必须设在
-enter-active/-leave-active里,不能只写在-enter - 如果图片初始是隐藏的(
v-if切换),确保v-if绑定的数据响应式更新,否则<transition></transition>不会触发
图片加载完成后再触发动画更自然
直接对未加载完的 <image></image> 应用淡入,会出现“先闪一下空白再淡入”的割裂感。应该等图片加载成功后才显示并启动动画:
<transition name="fade"><image v-if="loaded" :src="src" true></image></transition>
这样能避免白屏闪烁。注意:uni-app 的 <image></image> 组件 @load 事件在部分安卓小程序里有兼容性问题(如旧版微信开发者工具),若遇到不触发,可降级为监听 @error + 定时检测 naturalWidth 是否大于 0。
- 不要用
v-show替代v-if,否则<transition></transition>不生效 - 如果用
<swiper></swiper>轮播,其内置:duration控制的是滑动动画时长,和淡入淡出无关,需额外套一层<transition></transition> - 多图轮播时,每个
swiper-item都要单独包裹<transition></transition>,否则动画会错乱
真正要注意的不是怎么写动画,而是什么时候让动画开始——图片资源是否就绪、DOM 是否已挂载、v-if 的响应是否及时,这些细节比动画本身更容易导致效果异常。











