Javascript 更改请求动画帧的速度

Javascript 更改请求动画帧的速度,javascript,typescript,animation,frontend,requestanimationframe,Javascript,Typescript,Animation,Frontend,Requestanimationframe,我使用以下代码将画布中的图像从一个位置移动到另一个位置: class Target { constructor(img, x_init, y_init, img_width = 100, img_height = 100) { this.img = img; this.x = x_init; this.y = y_init; this.img_width = img_width; this.img_heigh

我使用以下代码将画布中的图像从一个位置移动到另一个位置:

class Target {
    constructor(img, x_init, y_init, img_width = 100, img_height = 100) {
        this.img = img;
        this.x = x_init;
        this.y = y_init;
        this.img_width = img_width;
        this.img_height = img_height;
    }
    

    get position() {
        return this.x
    }

    move(canvas, x_dest, y_dest) {
        ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(this.img, this.x, this.y, this.img_width, this.img_height);
        if (this.x != x_dest) {
            if (this.x > x_dest) {
                this.x -=1;
            } else {
                this.x +=1;
            }
        }
        if (this.y != y_dest) {
            if (this.y > y_dest) {
                this.y -=1;
            } else {
                this.y +=1;
            }
        }
        if (this.x != x_dest || this.y != y_dest) {
            //setTimeout(this.move.bind(target, canvas, x_dest, y_dest), 0);
            window.requestAnimationFrame(this.move.bind(target, canvas, x_dest, y_dest));
        }
    }

}
这个代码的问题是:我无法控制速度,而且速度相当慢。。。 我如何控制速度并保持选择到达位置的想法?我找到了这个话题,但在我的例子中,我并没有找到任何有用的东西,当然是因为1像素的步长太小了,但我不知道该怎么做

[编辑]以下是我想要做的(当红色圆圈缩小时,我必须在2秒内添加一条记录)。很明显,我是按照pid指令做的。再次感谢他

(函数(){
功能睡眠(ms){
返回新承诺(resolve=>setTimeout(resolve,ms));
}
var canvas=document.getElementById(“校准器”);
var ctx=canvas.getContext('2d');
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
常数点=[{
“x”:0,
“y”:0
},
{
“x”:画布宽度/2-100,
“y”:0
},
{
“x”:画布宽度-100,
“y”:0
},
{
“x”:0,
“y”:画布高度/2-100
},
{
“x”:画布宽度/2-100,
“y”:画布高度/2-100
},
{
“x”:画布宽度-100,
“y”:画布高度/2-100
},
{
“x”:0,
“y”:画布高度-100,
},
{
“x”:画布宽度/2-100,
“y”:画布高度-100
},
{
“x”:画布宽度-100,
“y”:画布高度-100
}
]
函数生成器线性(x0,y0,x1,y1,dt){
返回(t)=>{
设f0,f1;
f0=t>=dt?1:t/dt;//线性插值(又称lerp)
f1=1-f0;
返回{
“x”:f1*x0+f0*x1,//实际上是矩阵乘法
“y”:f1*y0+f0*y1
};
};
}
函数生成器滑动(x0,y0,x1,y1,r0,dt){
返回(t)=>{
var f0=t>=dt?0:dt-t;
var f1=t>=dt?1:dt/t;
变量f2=1-f1;
返回{
“x”:f2*x0+f1*x1,
“y”:f2*y0+f1*y1,
“r”:f0*r0
};
};
}
函数create_path_circle(){
var nbPts=点。长度;
var路径=[];
对于(变量i=0;i{
ctx=canvas.getContext('2d');
ctx.图纸图像(图像、位置x、位置y、图像宽度、图像高度);
}
}
函数renderCircle(){
返回(pos)=>{
ctx=canvas.getContext('2d');
ctx.beginPath();
ctx.弧(位置x+50,位置y+50,位置r,0,2*数学PI);
ctx.fillStyle=“#FF0000”;
ctx.fill();
ctx.stroke();
}
}
函数generatePath(路径){
让我,t;
//固定时间
t=0;
对于(i=0;i{
while(path.length>1&&t>=路径[0]。结束){
path.shift();//删除旧段,但保留最后一段
}
返回路径[0]。段(t-路径[0]。开始);//时间已更正
};
}
var base_image=新图像();
base_image.src=https://www.pngkit.com/png/full/17-175027_transparent-crosshair-sniper-scope-reticle.png';
常量精灵=[
{
“移动”:生成路径(路径圆),
“已创建”:performance.now(),
“渲染”:renderCircle()
},
{
“移动”:生成路径(路径目标),
“已创建”:performance.now(),
“渲染”:渲染(基本图像,100100)
}
];
常数更新=()=>{
让我们现在开始;
ctx.fillStyle=“#FFFFFF”;
ctx.fillRect(0,0,canvas.width,canvas.height);
//放在一边,以便为相同的ms绘制所有精灵
现在=性能。现在();
for(精灵中的变量精灵){
sprite.render(sprite.move((现在-sprite.created)/1000));
}
window.requestAnimationFrame(更新);
};
window.requestAnimationFrame(更新);
})();

校准

编辑:添加了另一个移动示例(查看青色方块)

要回答您关于如何在固定时间内到达“某处”的评论,您可以将大多数函数线性化,然后通过固定时间来求解方程。这对于线性运动来说很容易,但对于复杂的情况,例如沿着非线性函数移动(例如对数螺旋线),则相当困难

对于以恒定速度(无加速/减速)从
(x0,y0)
(x1,y1)
在时间
dt
上的线性运动,可以使用线性插值:

函数生成器线性(x0,y0,x1,y1,dt)
{
返回(t)=>{
设f0,f1;
f0=t>=dt?1:t/dt;//线性插值(又称lerp)
f1=1-f;
返回{
“x”:f0*x0+f1*x1,//实际上是一个