版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第如何利用JS实现时间轴动画效果目录css动画什么是时间轴动画?动画对象动画函数思考总结
css动画
在前端开发中,一些简单的动效往往是使用css3的@keyframes来实现的,如:
.div1{
width:100px;
height:100px;
background:red;
animation:changeColor2s;
@keyframeschangeColor{
0%{background:red;}
50%{background:yellow;}
100%{background:blue;}
假如设定的时间是2s,那么这段动画的描述是这样的:在2秒内,某元素的背景色由红色变为黄色,又变为蓝色了。
假定有这样一个需求:
一个动画共持续4秒,在0-2秒内div1从红色变为黄色再变为蓝色,div2在2-4秒内宽度由100px变为200px。
.div1{
width:100px;
height:100px;
background:red;
animation:changeColor2sforwards;
@keyframeschangeColor{
0%{background:red;}
50%{background:yellow;}
100%{background:blue;}
.div2{
width:100px;
height:100px;
background:pink;
animation:changeWidth4sforwards;
@keyframeschangeWidth{
0%{width:100px}
50%{width:100px}
100%{width:200px}
看起来好像也还行,那么div1在第1秒变色,div2在2-5秒内变形,div3在3-7秒内变色变形,div4在4-10秒内旋转...,然后这些一起构成了需求想要的动画效果。
这样的话我们要找出整个动画的总时长,然后每个div的运动时间算出相对总时间的百分比区域,然后设定keyframe动画。
到这里keyframes貌似就有些复杂度了,我们平时一直在用keyframes,那么keyframes或者说动画的本质是什么?
由于人类视觉停留的原理,这样一张张图片连续展示就看起来像动画了,翻书动画或者显示器逐帧刷新显示都是利用了这个原理。在动画创作时,除了像素、2d动画还在逐帧绘制,大多数类型的动画都已在编辑时方便将帧转换为时间进行计算。
keyframes作为一个高度定制化的产物,只是在名称上对帧这个概念进行了保留,它对单个元素的动画编辑是简单方便的。
但通过示例二就可以看出,它没有对多元素组合动画进行针对性的设计,代码上div1和div2是没有逻辑关系表现的(虽然在最终运行时会进行组合,即页面上的多数动画是维护在一个计时器里执行的。),它们没有统一的时间轴,没有父级包裹,要实现这些,需要编码者自己维护。
什么是时间轴动画?
对有过视频剪辑经验的人来说,视频剪辑的核心工具:基于时间轴的多轨视频编辑器是极为高效和方便的,它实现了对多个动画/特效片段的整合,称为时间轴动画。我们可以基于此实现一个简易的js版本来针对多元素长时间的动画需求。
如图所示,整个视频由多段小动画交错拼合而成,公用一个时间轴,由此构成了整个视频。
类比到前端,我们也可以用类似的方法,以时间轴为基准,整合多个动画片段。
我们可以有以下思路:
先创建一个obj对象作为参数,我们称作动画对象,它是整个动画过程的描述。
再创建一个执行动画的函数,我们称作动画函数,它接受动画对象和一个回调函数(动画结束时执行)作为参数。
接下来就进入代码实现:
动画对象
我们首先看以下代码:
varanim=[
{//动画对象,可以多个
dom:document.getElementById('a1'),//dom对象
anim:[//动画数组,里面可为多个对象
style:'height',
//要改变的样式名称如width,height
from:'10rem',//样式的起始值要和to保持一致
to:'20rem',//样式的目标值要和from保持一致
start:0,//开始时间毫秒
end:100,//结束时间毫秒
style:'width',
from:'10rem',
to:'20rem',
start:100,
end:200,
style:'transform',
from:'rotate(20deg)',
to:'rotate(40deg)',
start:0,
end:2000,
dom:document.getElementById('a2'),
anim:[
style:'background',
from:'rgba(0.0,0.0,0.0,1)',
to:'rgba(255,0,100,0.5)',
start:0,
end:3000,
timeLineAnim(anim,function(){
console.log('animationfinished');
anim对象里清晰的描述了每个对象有几个动画,每个动画是怎么进行的。
然后anim对象作为一个参数传入了timeLineAnim中,在实际执行中它会进行如下操作:
div1在0.1秒内高度从10rem变为了20rem,接着变宽,同时前2秒内还在旋转。
div2在0-3秒内颜色由rgba(0,0,0,1)变为rgba(255,0,100,0.5)。
在3秒后,动画结束,控制台打出了animationfinished。
它的效果如下图所示:
动画函数
实现这个动画函数,首先简单构思下思路:1:将参数anim中的from、to的数字提取出来,便于计算。
2:开启requestAnimationFrame,根据时间间隔和动画参数anim计算出当前帧的css,并赋到对应的dom元素上。
3:在最后一个动画结束后,关闭requestAnimationFrame,并执行回调函数。
现在就进入编码阶段:在以上思路的基础上,我们在具体实现的过程中,通过timeCount来判断动画是否结束,使用cssText进行样式的赋值。
functiontimeLineAnim(arr,cb){
initData:对数据进行初始化,将from、to中的信息转为数字,计算出动画的个数
setCss:逐帧执行,根据传入的单个动画对象和每帧的时间间隔,计算出当前帧的样式,并修改元素的style值
functioninitData(obj){
varreg=/[\d\.]+/g;
varnumArrFrom=obj.from.match(reg);
varnumArrTo=obj.to.match(reg);
if(!numArrFrom||!numArrTo||numArrFrom.length==0||numArrTo.length==0||numArrFrom.length!=numArrTo.length){
console.warn('数据输入错误');
for(vari=0;inumArrFrom.length;i++){
numArrFrom[i]=parseFloat(numArrFrom[i]);
numArrTo[i]=parseFloat(numArrTo[i]);
varstrArr=obj.from.split(reg);
if(numArrFrom.length=0){return;};
animCount++;
return{
strArr:strArr,
numArrFrom:numArrFrom,
numArrTo:numArrTo,
totalLength:strArr.length+numArrFrom.length,
isEnd:false,
functionsetCss(obj,timeCount){
varstyleStr='';
vartempCount=animCount;
//将对象的多个动画,根据时间计算出样式,并合并
for(vari=0;iobj.anim.length;i++){
vartarget=obj.anim[i];
if(timeCounttarget.start!target.initData.isEnd){
//根据起止时间计算出当前动画进度
varpercent=(timeCount-target.start)/(target.end-target.start);
if(percent=1){
percent=1;
target.initData.isEnd=true;
tempCount--;
styleStr+=getValue(percent);
obj.dom.style.cssText+=';'+styleStr;
animCount=tempCount;
//这里进行单个动画每帧样式的生成,这里是匀速运动
functiongetValue(percent){
varnumFrom=target.initData.numArrFrom;
varnumTo=target.initData.numArrTo;
vararr=[];
for(vari=0;inumFrom.length;i++){
arr.push(numFrom[i]+(numTo[i]-numFrom[i])*percent);
varnumIndex=0;
varstrIndex=0;
varturnForNum=false;
varstr=target.style+':';
for(vari=0;itarget.initData.totalLength;i++){
if(turnForNum){
str+=arr[numIndex];
numIndex++;
turnForNum=false;
else{
str+=target.initData.strArr[strIndex];
strIndex++;
turnForNum=true;
returnstr+';';
//主体逻辑:初始化数据、帧动画、动画结束执行回调
varanimCount=0;
for(vari=0;iarr.length;i++){
for(varj=0;jarr[i].anim.length;j++){
arr[i].anim[j].initData=initData(arr[i].anim[j]);
this.timercancelAnimationFrame(this.timer);
var_this=this;
(functionanimate(timeCount){
if(animCount0){
for(vari=0;iarr.length;i++){
setCss(arr[i],timeCount);
_this.timer=requestAnimationFrame(animate);
else{
cancelAnimationFrame(_this.timer);
cbcb();
})();
伸手党可直接复制运行。至此,一个基于时间轴的简易动画函数就完成了,不到100行的代码就可以使你愉快的使用声明式的方式编
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 泉州消防安全会议纪要
- 前列腺增生患者的健康教育内容
- 八分钟护理说课:老年护理要点分享
- 门诊护理团队建设与管理
- 应急物资储备管理操作手册
- 旋耕机安全操作与维修规程
- 化工企业双重预防机制建设指引
- 农残超标地块复种技术修复方案
- 护理手卫生的感染预防
- 手动喷雾器精准施药技术标准
- 第六节 学生实验:设计制作简易直流电动机说课稿-2025-2026学年中职基础课-电工电子类-高教版(2021)-(物理)-55
- 2025年及未来5年中国RTP管行业市场供需格局及行业前景展望报告
- 智慧树知道网课《企业法务概论》课后章节测试满分答案
- 2024秋九年级化学上册 4.3 水的组成说课稿 (新版)新人教版
- 绿化保洁安全培训课件
- 疑难病例讨论制度
- 人工流产并发症
- 2025年四川省广安市中考物理试题(原卷版)
- 2025年安徽省高考化学试卷真题(含答案详解)
- 设备安装、调试、验收管理制度
- 2024年贵州省高考化学试题含答案解析
评论
0/150
提交评论