We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
用js的setInterval实现动画有很多缺点,首先是精度问题,如果有大量的dom操作,动画间隔是不准确的。 requestAnimationFrame会将所有的dom操作集中起来,跟随浏览器的刷新频率(60帧)一次完成,会区分隐藏不可见的元素,性能更好。 但是requestAnimationFrame和setInterval对时间的处理方式是不一样的,setInterval直接传递一个时间间隔(ms单位),以此执行回调函数
setInterval(() => { // }, 1000)
而requestAnimationFrame会传递一个时间戳timestamp,表示自页面加载以来,回调函数被执行的时刻,一直增大。
13.502 30.098 46.995 63.45 ...
通过时间戳可以得到时间间隔从而进行处理,也就是说每个动画还需要一个变量来记录时间来和timestamp进行对比。
var time = 0; function A(t) { requestAnimationFrame(A) console.log("距离上一次执行的时间间隔", t - time) time = t } A() // 距离上一次执行的时间间隔 16.64300000000003 // 距离上一次执行的时间间隔 16.663000000000466 // 距离上一次执行的时间间隔 16.87199999999939 // 距离上一次执行的时间间隔 16.472000000000662 // 距离上一次执行的时间间隔 16.639999999999418 // 距离上一次执行的时间间隔 16.649000000000342 // 距离上一次执行的时间间隔 16.842999999999847 // 距离上一次执行的时间间隔 16.509000000000015 // 距离上一次执行的时间间隔 16.61999999999989 // 距离上一次执行的时间间隔 16.646999999999935 // 距离上一次执行的时间间隔 16.789999999999964 // 距离上一次执行的时间间隔 16.605999999999767 // 距离上一次执行的时间间隔 17.220000000000255 // 距离上一次执行的时间间隔 16.038000000000466 // 距离上一次执行的时间间隔 16.787999999999556 // 距离上一次执行的时间间隔 16.576000000000022 // 距离上一次执行的时间间隔 16.699999999999818 // 距离上一次执行的时间间隔 16.634000000000015 // 距离上一次执行的时间间隔 16.72400000000016 // 距离上一次执行的时间间隔 16.775000000000546
由上面的例子可以看出,requestAnimationFrame需要自行控制执行的时间间隔,假如要实现一个秒计时器。
var interval = 1000 var lastTime = 0 function SecondTimer(t) { requestAnimationFrame(SecondTimer) if(t - lastTime >= interval) { console.log("1s到了") lastTime = t } } SecondTimer()
function Timer(interval, fn) { this.lastTime = 0 this.interval = interval this.timer = null (function loop(timestamp){ that.timer = requestAnimationFrame(loop) if(timestamp - that.lastTime > that.interval) { typeof fn == "function" && fn() that.lastTime = timestamp; } })() } Timer.prototype.clear = function() { cancelAnimationFrame(this.timer) } var secondTimer = new Timer(1000, () => { console.log("1s到了") }) var second10Timer = new Timer(10000, () => { console.log("10s到了") }) // 15s后清除 setTimeout(() => { secondTimer.clear() second10Timer.clear() }, 15000)
先构建一个舞台stage,然后所有的动画元素都视为stage的子元素,stage以一个固定的频率刷新,子元素各自进行自己的动画
<canvas id="stage"></canvas>
window.onload = function() { var stage = document.getElementById("stage") stage.width = 300 stage.height = 300 stage.childrens = [] var ctx = stage.getContext("2d") function Circle(x, y, r, c, fps) { this.x = x this.y = y this.r = r this.c = c this.fps = fps this.lt = 0 this.init() } Circle.prototype.move = function() { if(this.x <= 300) { this.x += 1 } if(this.y <= 300) { this.y += 1 } } Circle.prototype.draw = function() { ctx.beginPath() ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2) ctx.strokeStyle = this.c ctx.stroke() ctx.closePath() } Circle.prototype.init = function() { this.draw() } Circle.prototype.update = function(t) { if(t - this.lt > this.fps) { this.move() this.lt = t } this.draw() } var c = new Circle(0, 0, 20, 'red', 16) stage.childrens.push(c) var c2 = new Circle(0, 0, 20, 'blue', 32) stage.childrens.push(c2) var c3 = new Circle(0, 0, 20, 'yellow', 64) stage.childrens.push(c3) stage.update = function(timestamp) { requestAnimationFrame(stage.update) ctx.clearRect(0, 0, stage.width, stage.height) stage.childrens.forEach(item => { item.update(timestamp) }) } stage.update() }
此时我们只需要改变元素的动画形式,就可以得到效果。
Circle.prototype.move = function() { // if(this.x <= 300) { // this.x += 1; // } // if(this.y <= 300) { // this.y += 1; // } this.r = Math.random() * 50 }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
用js的setInterval实现动画有很多缺点,首先是精度问题,如果有大量的dom操作,动画间隔是不准确的。
requestAnimationFrame会将所有的dom操作集中起来,跟随浏览器的刷新频率(60帧)一次完成,会区分隐藏不可见的元素,性能更好。
但是requestAnimationFrame和setInterval对时间的处理方式是不一样的,setInterval直接传递一个时间间隔(ms单位),以此执行回调函数
而requestAnimationFrame会传递一个时间戳timestamp,表示自页面加载以来,回调函数被执行的时刻,一直增大。
通过时间戳可以得到时间间隔从而进行处理,也就是说每个动画还需要一个变量来记录时间来和timestamp进行对比。
自定义时间间隔
由上面的例子可以看出,requestAnimationFrame需要自行控制执行的时间间隔,假如要实现一个秒计时器。
封装一个定时器
实现canvas动画
先构建一个舞台stage,然后所有的动画元素都视为stage的子元素,stage以一个固定的频率刷新,子元素各自进行自己的动画
此时我们只需要改变元素的动画形式,就可以得到效果。
The text was updated successfully, but these errors were encountered: