|
|
1
SergGr
7 年前
你的问题,你的动画是基于
requestAnimationFrame
它不能保证在固定的时间间隔内进行调度,因此使用固定速度的逻辑
this.distance += this.speed;
不适合你,你想计算一下
this.distance
基于实际运行时间
this.elapsed = Date.now() - this.started
如果是这样的话,变化是微不足道的:对于任何给定的时刻,当前距离应该是整个距离的一部分,因为当前经过的时间是整个时间的一部分。所以就你的代码而言:
this.distance = distance * this.elapsed / this.time;
或者更新您的演示:
var cvs = document.querySelector('canvas'),
ctx = cvs.getContext('2d'),
w, h, cx, cy,
resize = function () {
w = cvs.width = window.innerWidth;
cx = w / 2;
h = cvs.height = window.innerHeight;
cy = h / 2;
},
tools = {
rnd: (min, max) => Math.floor(Math.random() * (Math.floor(max) - Math.ceil(min) + 1)) + Math.ceil(min),
flt: (min, max, dec) => parseFloat((Math.random() * (min - max) + max).toFixed(dec)),
distance: (p1, p2) => Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)),
rftv: (p1, p2) => Math.atan2(p2.y - p1.y, p2.x - p1.x)
},
globalStart = Date.now(),
loop = function () {
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, w, h);
var globalElapsed = Date.now() - globalStart;
ctx.font = '48px serif';
ctx.fillStyle = 'hsl(50, 100%, 50%)';
var text = (pool.length > 0) ? globalElapsed / 1000 : "End";
ctx.fillText(text, 40, 50);
for (var i = pool.length - 1; i >= 0; i--) {
pool[i].move();
ctx.save();
ctx.beginPath();
ctx.arc(pool[i].x, pool[i].y, pool[i].r, Math.PI * 2, 0);
ctx.fillStyle = 'hsl(100, 100%, 50%)';
ctx.fill();
ctx.closePath();
ctx.restore();
ctx.save();
ctx.beginPath();
ctx.arc(pool[i].ix, pool[i].iy, pool[i].r, Math.PI * 2, 0);
ctx.strokeStyle = 'hsl(100, 100%, 50%)';
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.save();
ctx.beginPath();
ctx.arc(pool[i].dx, pool[i].dy, pool[i].r, Math.PI * 2, 0);
ctx.strokeStyle = 'hsl(100, 100%, 50%)';
ctx.stroke();
ctx.closePath();
ctx.restore();
if (pool[i].remaining <= 0) {
pool.splice(i, 1);
}
}
requestAnimationFrame(loop);
},
pool = [],
last_spawn = 0,
spawn_interval = 0,
spawn_limit = 1,
spawn = function () {
if (Date.now() - last_spawn > spawn_interval) {
last_spawn = Date.now();
for (var i = 0; i < spawn_limit; i++) {
pool.push(new particle());
}
}
},
particle = function () {
var exvec = tools.rnd(20, w - 20),
eyvec = tools.rnd(20, h - 20),
svecs = {
x: cx,
y: cy
},
evecs = {
x: exvec,
y: eyvec
},
rad = tools.rftv(svecs, evecs),
distance = tools.distance(svecs, evecs);
this.time = 10 * 1000;
this.elapsed = 0;
this.started = Date.now();
this.ix = cx;
this.iy = cy;
this.dx = exvec;
this.dy = eyvec;
this.x = cx;
this.y = cy;
this.r = 10;
this.rad = rad;
this.period = distance / 2;
this.distance = 0;
this.total = distance;
this.remaining = distance;
this.amplitude = distance / 4;
this.move = function () {
this.elapsed = Date.now() - this.started;
this.distance = distance * this.elapsed / this.time;
this.remaining = this.total - this.distance;
this.x = this.ix + Math.cos(this.rad) * this.distance;
this.y = this.iy + Math.sin(this.rad) * this.distance;
const deviation = Math.sin(this.distance * Math.PI / this.period) * this.amplitude;
this.x += Math.sin(this.rad) * deviation;
this.y -= Math.cos(this.rad) * deviation;
};
};
resize();
loop();
window.onresize = function () {
resize();
};
spawn();
body {
overflow:hidden;
}
canvas {
position:absolute;
top:0;
left:0;
}
<canvas></canvas>
注意
-
我变了
this.time
到10秒到秒,这样动画更容易跟踪
-
我添加了
globalStart
和
globalElapsed
在内部绘制实际时间
loop
-
我减小了曲线的尺寸,以便更好地适应较小的区域。
|