一、前言
什么是序列帧?为什么要播放序列帧,它可以做什么?
序列帧是指将一系列连续的图像帧按照一定的顺序播放,从而产生连续动画效果的技术。每一帧都是一个静止的图像,但通过连续地播放这些图像,人眼会感知到动态的效果。在计算机图形和动画领域,序列帧常用于制作动画、游戏、电影等多媒体内容。
通常情况下,序列帧的制作过程包括以下步骤:
设计和绘制每一帧的图像内容:根据动画或场景的需求,设计并绘制出一系列静止的图像帧。
编排图像帧的顺序:确定每一帧的播放顺序,以便按照一定的速率连续播放。
将图像帧导入动画制作工具或游戏引擎:使用动画制作软件或游戏引擎,将设计好的图像帧导入,并按照预定的顺序进行排列和编辑。
设置播放速度和循环方式:调整动画的播放速度和循环方式,使其符合预期的效果。
导出动画文件:将编辑好的序列帧动画导出为视频文件、GIF 动画或者游戏引擎所支持的动画格式,以便在目标平台上播放或使用。
序列帧技术在动画制作、游戏开发以及其他多媒体应用中被广泛使用,因为它能够提供高度灵活性和精细的控制,同时也能够实现各种复杂的动画效果
二、在前端如何实现序列帧的播放
在之前文章中通过了请求动画帧requestAnimationFrame + vue中的ref方法,不断地更新img标签的src属性来实现,这种方式实现比较容易,适合图片比较小也按照每一帧都切好的图片,但是犹豫图片太多了,在大量使用的时候,通常容易造成网络堵塞,加载时间过长或者超时等,那有什么办法解决这个问题吗?
解决办法:
上面提到过多的图片请求会造成网络堵塞,那我们只需要将图片合成一个不就行了,这样子只需一个请求就搞定了,制作精灵图网站这里给一个感觉挺好用的点击这里
实现的原理网上很多,但是我简单说一下,有可以横着也就是朝着x轴的方向,也有竖着的就是一朝着y轴方向,周期性按顺序的截取图片的一个片段,往复循环就可以达到我们的效果,这个如果是学习过着色器,应该就很好理解
接下来就是直接带上代码,我用的是竖直方向的精灵图
interface Props {
// 雪碧图url
framesUrl: string;
// 帧数
frequency: number;
// 帧数
frequencySum: number;
// 是否循环
loop?: boolean;
// 宽度
width?: number;
// 高度
height?: number;
}
const faults = withDefaults(defineProps
framesUrl: "./framesImages/parkOverview/大标题.png",
loop: true,
frequency: 10,
frequencySum: 100,
width: 100,
height: 100
});
.SequenceFrame {
width: v-bind('faults.width + "px"');
height: v-bind('faults.height + "px"');
animation: move v-bind('(faults.frequencySum / faults.frequency) + "s"') steps(v-bind('faults.frequencySum')) infinite;
background-size: v-bind('faults.width + "px"') v-bind('(faults.height * faults.frequencySum) + "px"');
background-repeat: no-repeat;
/* animation: move 2s steps(28) infinite;*/
}
@keyframes move {
from {
background-position: 0 0;
}
to {
background-position: 0 v-bind('-(faults.height * faults.frequencySum) + "px"');
}
}
这里用到了vue3.4的新特性,v-bind,用着很方便,可以实现变量在js和css中绑定,不理解的可以去vue的官网看看
使用方法看代码
精灵图长啥样呢,大概是这样,数值分布,每一帧,用的时候,需要知道每一帧的宽高,不然截图图像的时候不准确