前端动图动效方案
刀刀
0字
0分钟
2026/8/16
图片方案
| 名称 | 体积 | 质量 | 兼容性 | 透明底支持 |
|---|---|---|---|---|
| GIF | 同等质量下最大 | 质量低 | 基本全兼容 | 无法透明底 |
| aPNG | 同等质量下小于 gif | 质量高 | 兼容比较新的现代浏览器 | 支持透明底 |
| WebP | 同等质量下小于 apng | 质量高 | 比 apng 好,但是 ios 比 apng 差 | 支持透明底 |
| AVIF | 同等质量下最小 | 质量极高 | 非常差,chrome 需要 85+,ios 要 16+ | 支持透明底 |
最佳实践
优先使用WebP作为首选,从大小和兼容性上都比aPNG好,而AVIF兼容性太差,不去考虑。
同时还可以针对动图做一个降级方案,优先使用WebP,如果浏览器不支持WebP,则使用aPNG,如果aPNG也不支持,则使用保底方案GIF。
可以写一个 js 函数,用于处理动图降级处理。核心思路为:
new Image创建一个img标签,分别加载AVIF和WebP,哪个成功用哪个- 判断好支持哪个再去挂载DOM,因此需要用到Promise实现异步操作
- 异步执行完毕后再去加载Vue
js
export function imgSupport() {
return new Promise((resolve, reject) => {
window.picSupport = 'low'
const imgAvif = new Image()
imgAvif.src = 'data:image/avif;base64,YWN0aXZlL3d3dy5nb29nbGUuY29tCg=='
imgAvif.onload = () => {
// 支持avif
window.picSupport = 'avif'
resolve()
}
imgAvif.onerror = () => {
// 不支持avif,试试加载webp
const imgWebp = new Image()
imgWebp.src =
'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA'
imgWebp.onload = () => {
// 支持webp
window.picSupport = 'webp'
resolve()
}
imgWebp.onerror = () => {
// 也不支持webp,则默认low用gif
resolve()
}
}
})
}js
import { imgSupport } from './imgSupport.js'
import App from './App.vue'
imgSupport().then(() => {
createApp(App).mount('#app')
})注意,要提前准备好三张非常小的AVIF、WebP格式的图片(可以准备一个 1*1 的 png 图片,然后格式转换),然后转为Base64,直接写到代码中,用于判断浏览器是否支持AVIF和WebP,速度能更快点。
需确保使用真AVIF和WebP图片,不能通过文件重命名修改后缀的方式。推荐使用网站 ezgif 进行格式转换。
动画方案
| 名称 | 体积 | 质量 | 兼容性 | 开发者麻烦程度 | 制作工具 |
|---|---|---|---|---|---|
| CSS 动画 | 体积最小 | 高清无损 | 和CSS3兼容性一致,支持 keyframe 就能做,兼容性最好 | 麻烦,要写 html 配合 css | 自己写 |
| Canvas 动画 | 体积一般不大,吃运算内存 | 高清无损,但可能会卡 | 支持Canvas就行,兼容性比 css 差点 | 最麻烦,写大量 js 配合定时器更新动画 | 自己写 |
| Lottie | 体积一般,需要额外安装 lottie 播放库 | 高清无损,但可能会卡 | 需要支持SVG、CSS3、es5,要求稍微高点,chrome 45+,los9,andorid4 以下可能有问题 | 一键引入库直接使用 | AE,素材网站 |
lottie 的使用
使用
- 安装
lottie-web库 - 写入
div标签 - 引入
lottie对应的json文件并使用
vue
<script setup>
import lottie from 'lottie-web'
const container = ref(null)
const { lottieUrl, fallback } = defineProps(['lottieUrl', 'fallback'])
const canPlayerLottie = ref(true)
onMounted(() => {
if (!canPlayerLottie) return
// 不能直接拿来播放动画,而是要请求到json,拿json数据再去播放动画
axios.get(lottieUrl).then((res) => {
lottie.loadAnimation({
container: container.value, // 容器
renderer: 'svg', // 渲染方式,svg、canvas、html
loop: true, // 是否循环
autoplay: true, // 是否自动播放
animationData: res.data, // json数据
})
})
})
</script>
<template>
<!-- 可以播放lottie动画 -->
<div v-if="canPlayerLottie" ref="container"></div>
<!-- 不能播放用图片兜底 -->
<img v-else :src="fallback" />
</template>vue
<template>
<Lottie :lottieUrl="lottieUrl" :fallback="fallback" />
</template>
<script setup>
import Lottie from './components/lottie.vue'
const lottieUrl = 'https://assets10.lottiefiles.com/packages/lf20_4xqjvq.json'
const fallback =
'https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8a4b6b8f7f9b4d4e8a6f4c5e6f4b6b8f~tplv-k3u1fbpfcp-zoom-crop-mark:3024:3024:3024:1702.awebp?'
</script>注意
最好不用 id 获取容器,而是用 ref,因为Lottie只是一个小动画播放器,一个页面上可能会使用多个Lottie,如果用 id 获取容器,会导致重复 id 。
lottie 判断
Lottie的判断和图片的判断类似,也是写一个函数,判断是否支持SVG和requestAnimationFrame,如果都支持,则Lottie可以播放,否则不能播放。而判断的时机不能写在组件内,因为组件可能会多次加载,因此需要写一个全局的 js 函数,在 main.js 中调用。
js
import MobileDetect from 'mobile-detect'
export function lottieSupport() {
return new Promise((resolve, reject) => {
window.canLottie = false
const canSvg =
!!docuent.createElementNS &&
!!docuent.createElementNS('http://www.w3.org/2000/svg', 'svg')
.createSVGRect
const canRequestAnimation = !!window.requestAnimationFrame
// ios的隐私策略,导致读取版本会有点困难,借助mobileDetect库帮助读取
const md = new MobileDetect(window.navigator.userAgent)
// 判断是否是低端机型
const isLowEndAndroid = /Android [2-4]/.test(navigator.userAgent())
const isOldIOS = md.is('iPhone') && parseFloat(md.version('iPhone')) < 10
if (canSvg && canRequestAnimation && !isLowEndAndroid && !isOldIOS) {
window.canLottie = true
}
resolve()
})
}js
import { lottieSupport } from './lottieSupport.js'
import App from './App.vue'
lottieSupport().then(() => {
createApp(App).mount('#app')
})lottie 本质
Lottie本质是SVG动画,只不过是用JSON文件描述SVG动画,然后通过Lottie库解析JSON文件,生成SVG动画。降级建议
Lottie建议如果不支持或者低端机型会引起卡顿,可以降级为png 或GIF。