博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS进阶篇--window.requestAnimationFrame与Tween.js配合使用实现动画缓动效果
阅读量:7309 次
发布时间:2019-06-30

本文共 9106 字,大约阅读时间需要 30 分钟。

window.requestAnimationFrame

概述

window.requestAnimationFrame()这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数,以满足开发者操作动画的需求。这个方法接受一个函数为参,该函数会在重绘前调用。

注意: 如果想得到连贯的逐帧动画,函数中必须重新调用 requestAnimationFrame()。

如果你想做逐帧动画的时候,你应该用这个方法。这就要求你的动画函数执行会先于浏览器重绘动作。通常来说,被调用的频率是每秒60次,但是一般会遵循W3C标准规定的频率。如果是后台标签页面,重绘频率则会大大降低。

回调函数只会被传入一个DOMHighResTimeStamp参数,这个参数指示当前被 requestAnimationFrame 序列化的函数队列被触发的时间。因为很多个函数在这一帧被执行,所以每个函数都将被传入一个相同的时间戳,尽管经过了之前很多的计算工作。这个数值是一个小数,单位毫秒,精确度在 10 µs。

语法

requestID = window.requestAnimationFrame(callback);// Firefox 23 / IE10 / Chrome / Safari 7 (incl. iOS)requestID = window.mozRequestAnimationFrame(callback);// Firefox < 23requestID = window.webkitRequestAnimationFrame(callback);// Older versions Chrome/Webkit

参数

callback在每次需要重新绘制动画时,会调用这个参数所指定的函数。这个回调函数会收到一个参数,这个 DOMHighResTimeStamp 类型的参数指示当前时间距离开始触发 requestAnimationFrame 的回调的时间。

返回值

requestID 是一个长整型非零值,作为一个唯一的标识符.你可以将该值作为参数传给 window.cancelAnimationFrame() 来取消这个回调函数。

例子

window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;var start = null;var d = document.getElementById('SomeElementYouWantToAnimate');function step(timestamp) {   if (start === null) start = timestamp;  var progress = timestamp - start;  d.style.left = Math.min(progress/10, 200) + "px";  if (progress < 2000) {    requestAnimationFrame(step);  }}requestAnimationFrame(step);

Tween.js

tween.js源码如下:

/* * Tween.js * t: current time(当前时间); * b: beginning value(初始值); * c: change in value(变化量); * d: duration(持续时间)。 * you can visit 'http://easings.net/zh-cn' to get effect*/var Tween = {    Linear: function(t, b, c, d) { return c*t/d + b; },    Quad: {        easeIn: function(t, b, c, d) {            return c * (t /= d) * t + b;        },        easeOut: function(t, b, c, d) {            return -c *(t /= d)*(t-2) + b;        },        easeInOut: function(t, b, c, d) {            if ((t /= d / 2) < 1) return c / 2 * t * t + b;            return -c / 2 * ((--t) * (t-2) - 1) + b;        }    },    Cubic: {        easeIn: function(t, b, c, d) {            return c * (t /= d) * t * t + b;        },        easeOut: function(t, b, c, d) {            return c * ((t = t/d - 1) * t * t + 1) + b;        },        easeInOut: function(t, b, c, d) {            if ((t /= d / 2) < 1) return c / 2 * t * t*t + b;            return c / 2*((t -= 2) * t * t + 2) + b;        }    },    Quart: {        easeIn: function(t, b, c, d) {            return c * (t /= d) * t * t*t + b;        },        easeOut: function(t, b, c, d) {            return -c * ((t = t/d - 1) * t * t*t - 1) + b;        },        easeInOut: function(t, b, c, d) {            if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;            return -c / 2 * ((t -= 2) * t * t*t - 2) + b;        }    },    Quint: {        easeIn: function(t, b, c, d) {            return c * (t /= d) * t * t * t * t + b;        },        easeOut: function(t, b, c, d) {            return c * ((t = t/d - 1) * t * t * t * t + 1) + b;        },        easeInOut: function(t, b, c, d) {            if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;            return c / 2*((t -= 2) * t * t * t * t + 2) + b;        }    },    Sine: {        easeIn: function(t, b, c, d) {            return -c * Math.cos(t/d * (Math.PI/2)) + c + b;        },        easeOut: function(t, b, c, d) {            return c * Math.sin(t/d * (Math.PI/2)) + b;        },        easeInOut: function(t, b, c, d) {            return -c / 2 * (Math.cos(Math.PI * t/d) - 1) + b;        }    },    Expo: {        easeIn: function(t, b, c, d) {            return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;        },        easeOut: function(t, b, c, d) {            return (t==d) ? b + c : c * (-Math.pow(2, -10 * t/d) + 1) + b;        },        easeInOut: function(t, b, c, d) {            if (t==0) return b;            if (t==d) return b+c;            if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;            return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;        }    },    Circ: {        easeIn: function(t, b, c, d) {            return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;        },        easeOut: function(t, b, c, d) {            return c * Math.sqrt(1 - (t = t/d - 1) * t) + b;        },        easeInOut: function(t, b, c, d) {            if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;            return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;        }    },    Elastic: {        easeIn: function(t, b, c, d, a, p) {            var s;            if (t==0) return b;            if ((t /= d) == 1) return b + c;            if (typeof p == "undefined") p = d * .3;            if (!a || a < Math.abs(c)) {                s = p / 4;                a = c;            } else {                s = p / (2 * Math.PI) * Math.asin(c / a);            }            return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;        },        easeOut: function(t, b, c, d, a, p) {            var s;            if (t==0) return b;            if ((t /= d) == 1) return b + c;            if (typeof p == "undefined") p = d * .3;            if (!a || a < Math.abs(c)) {                a = c;                 s = p / 4;            } else {                s = p/(2*Math.PI) * Math.asin(c/a);            }            return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);        },        easeInOut: function(t, b, c, d, a, p) {            var s;            if (t==0) return b;            if ((t /= d / 2) == 2) return b+c;            if (typeof p == "undefined") p = d * (.3 * 1.5);            if (!a || a < Math.abs(c)) {                a = c;                 s = p / 4;            } else {                s = p / (2  *Math.PI) * Math.asin(c / a);            }            if (t < 1) return -.5 * (a * Math.pow(2, 10* (t -=1 )) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;            return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p ) * .5 + c + b;        }    },    Back: {        easeIn: function(t, b, c, d, s) {            if (typeof s == "undefined") s = 1.70158;            return c * (t /= d) * t * ((s + 1) * t - s) + b;        },        easeOut: function(t, b, c, d, s) {            if (typeof s == "undefined") s = 1.70158;            return c * ((t = t/d - 1) * t * ((s + 1) * t + s) + 1) + b;        },        easeInOut: function(t, b, c, d, s) {            if (typeof s == "undefined") s = 1.70158;             if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;            return c / 2*((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;        }    },    Bounce: {        easeIn: function(t, b, c, d) {            return c - Tween.Bounce.easeOut(d-t, 0, c, d) + b;        },        easeOut: function(t, b, c, d) {            if ((t /= d) < (1 / 2.75)) {                return c * (7.5625 * t * t) + b;            } else if (t < (2 / 2.75)) {                return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;            } else if (t < (2.5 / 2.75)) {                return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;            } else {                return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;            }        },        easeInOut: function(t, b, c, d) {            if (t < d / 2) {                return Tween.Bounce.easeIn(t * 2, 0, c, d) * .5 + b;            } else {                return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;            }        }    }}Math.tween = Tween;

简介

动画运动算法名称如下:

  1. Linear:线性匀速运动效果;
  2. Quadratic:二次方的缓动(t^2);
  3. Cubic:三次方的缓动(t^3);
  4. Quartic:四次方的缓动(t^4);
  5. Quintic:五次方的缓动(t^5);
  6. Sinusoidal:正弦曲线的缓动(sin(t));
  7. Exponential:指数曲线的缓动(2^t);
  8. Circular:圆形曲线的缓动(sqrt(1-t^2));
  9. Elastic:指数衰减的正弦曲线缓动;
  10. Back:超过范围的三次方缓动((s+1)t^3 – st^2);
  11. Bounce:指数衰减的反弹缓动。

每个效果都分三个缓动方式,分别是:

  • easeIn:从0开始加速的缓动,也就是先慢后快;
  • easeOut:减速到0的缓动,也就是先快后慢;
  • easeInOut:前半段从0开始加速,后半段减速到0的缓动。

所有的这些缓动算法都离不开下面4个参数,t, b, c, d,含义如下:

/* * t: current time(当前时间); * b: beginning value(初始值); * c: change in value(变化量); * d: duration(持续时间)。*/

下面用最简单的线性匀速运动来解释下:

Tween.Linear = function(t, b, c, d) {     return c*t/d + b; }

比方说我们要从位置0的地方运动到100,时间是10秒钟,此时,b, c, d三个参数就已经确认了,b初始值就是0,变化值c就是100-0就是100,最终的时间就是10,此时,只要给一个小于最终时间10的值,Tween.Linear就会返回当前时间应该的坐标,例如,假设此时动画进行到第5秒,也就是t为5,则得到(截图自Chrome控制台):

图片描述

如何实际使用Tween.js中的缓动算法?

兼容写法:

window.requestAnimFrame = (function (callback,time) {    return window.requestAnimationFrame ||        window.webkitRequestAnimationFrame ||        window.mozRequestAnimationFrame ||        window.oRequestAnimationFrame ||        window.msRequestAnimaitonFrame ||        function (callback) {            window.setTimeout(callback, time);        };})();

我们要显示一个动画效果,例如,还是拿上面的线性效果举例,则代码可以变成:

var t = 0, b = 0, c = 100, d = 10;var step = function () {    // value就是当前的位置值    // 例如我们可以设置DOM.style.left = value + 'px'实现定位    var value = Tween.Linear(t, b, c, d);    t++;    if (t <= d) {         // 继续运动         requestAnimationFrame(step);    } else {        // 动画结束    }};

基本上,所有的动画使用都是这个套路。

参考地址:

缓动函数速查表:

转载地址:http://scenm.baihongyu.com/

你可能感兴趣的文章
运维学习-centos7上配置nginx基础配置
查看>>
linux 文件系统 备份
查看>>
Linux系统上的vim编辑器
查看>>
HTML5 & CSS3初学者指南(3) – HTML5新特性
查看>>
高性能Web服务器nginx
查看>>
给萌新的Flexbox简易入门教程
查看>>
『中级篇』Kubenetes简介(60)
查看>>
Java对象的序列化与反序列化
查看>>
eclipse快捷键整理
查看>>
vue.js 组件数据传递
查看>>
PHP常用数组函数小结
查看>>
lnmp平台的简单基础搭建
查看>>
链接器的应用(八)
查看>>
安卓手机上 K 歌,声音延迟怎么解决?
查看>>
cobbler批量化安装系统-CentOS7
查看>>
1周4次课 单用户模式,救援模式,克隆虚拟机,linux相互登录
查看>>
16.1 Tomcat介绍 16.2 安装jdk 16.3 安装Tomcat
查看>>
用Xshell连接VMware虚拟机
查看>>
Oracle的DDL语句不能回滚(直接提交)
查看>>
http,状态码集
查看>>