Javascript (画布)每隔几秒钟推送一个新项目

Javascript (画布)每隔几秒钟推送一个新项目,javascript,html,animation,canvas,Javascript,Html,Animation,Canvas,您好,提前谢谢您的帮助 我尝试每隔几秒钟推/创建一个新的“环”。我有一个带有X和Y两个变量的环。我遇到的问题是,如何得到一个新的环并增加变量?每个环都需要一个新的变量名? 以下是我到目前为止取得的成绩: 你可以在演示中看到一枚戒指是如何熄灭的,但我希望不止一枚戒指从我的眼睛中熄灭。举个例子,一个戒指走了,然后它等待一秒钟,然后射出另一个戒指,所以现在画布上有两个戒指,然后是3个,然后是4个,等等。。。。我已经想到了多种方法,比如使用数组和设置超时,但我不能把手指放在上面。我唯一的另一个想法是创

您好,提前谢谢您的帮助

我尝试每隔几秒钟推/创建一个新的“环”。我有一个带有X和Y两个变量的环。我遇到的问题是,如何得到一个新的环并增加变量?每个环都需要一个新的变量名? 以下是我到目前为止取得的成绩:

你可以在演示中看到一枚戒指是如何熄灭的,但我希望不止一枚戒指从我的眼睛中熄灭。举个例子,一个戒指走了,然后它等待一秒钟,然后射出另一个戒指,所以现在画布上有两个戒指,然后是3个,然后是4个,等等。。。。我已经想到了多种方法,比如使用数组和设置超时,但我不能把手指放在上面。我唯一的另一个想法是创建多个具有不同名称的变量,并使每个环递增,但这不是很D.R.Y

有什么帮助吗


如果我解释得不够好,请提问。再次感谢

将其添加到顶部的全局变量(并设置为圆之间的距离):

然后更新主循环,如下所示:

requestAnimationFrame(function print() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    var leftRing = new Ring(x, y);
    var rightRing = new Ring(x2, y2);
    var temp = startRadius;
    var temp2 = 0;

    while(temp > 0){
         leftRing.draw(ctx, startRadius - temp2 , 'red');
         rightRing.draw(ctx, startRadius - temp2 , 'red');   
         temp2 = temp2 + distanceApart;
         temp = temp - distanceApart;
    }

    startRadius += increase;

    requestAnimationFrame(print);
});
此处分叉:
(看起来记忆能力很强!)

将其添加到顶部的全局变量中(并设置为圆之间的任意距离):

然后更新主循环,如下所示:

requestAnimationFrame(function print() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    var leftRing = new Ring(x, y);
    var rightRing = new Ring(x2, y2);
    var temp = startRadius;
    var temp2 = 0;

    while(temp > 0){
         leftRing.draw(ctx, startRadius - temp2 , 'red');
         rightRing.draw(ctx, startRadius - temp2 , 'red');   
         temp2 = temp2 + distanceApart;
         temp = temp - distanceApart;
    }

    startRadius += increase;

    requestAnimationFrame(print);
});
此处分叉:
(看起来记忆能力很强!)

我会重写部分代码以启用此功能。例如,我将重写您的
Ring
类,如下所示:

var Ring = defclass({
    constructor: function (x, y, r) {
        this.x = x;
        this.y = y;
        this.r = r;
    },
    draw: function (context) {
        context.beginPath();
        context.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        context.stroke();
        return this;
    },
    addRadius: function (r) {
        return new Ring(this.x, this.y, this.r + r);
    }
});
function loop(last, rings) {
    var next = last + interval;

    context.clearRect(0, 0, width, height);

    var newRings = rings.map(function (ring) {
        return ring.draw(context).addRadius(delta);
    });

    var now = Date.now();

    setTimeout(loop, next - now, next,
        Math.floor((now - start) / 1000) === rings.length / 2 ?
            [left, right].concat(newRings) : newRings);
}
您的
类构造函数现在接受
x
y
和半径
r
addRadius
函数返回一个新的
Ring
,而不是对原始环进行变异。这很好,因为不变性使代码更易于使用。噢,
defclass
声明为:

function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}
然后我们为您的眼睛制作两个戒指:

var radius = 10;
var delta = 0.1;

var left = new Ring(cx - (cx / 3.6), cy - 5, radius);
var right = new Ring(cx + (cx / 3.6), cy - 10, radius);
之后,我们称之为动画循环:

var interval = 50 / 3;
var start = Date.now();
loop(start, [left, right]);
由于我们希望以60 FPS的速度播放,因此间隔为
1000/60
,可以简化为
50/3
。动画循环定义如下:

var Ring = defclass({
    constructor: function (x, y, r) {
        this.x = x;
        this.y = y;
        this.r = r;
    },
    draw: function (context) {
        context.beginPath();
        context.arc(this.x, this.y, this.r, 0, Math.PI * 2);
        context.stroke();
        return this;
    },
    addRadius: function (r) {
        return new Ring(this.x, this.y, this.r + r);
    }
});
function loop(last, rings) {
    var next = last + interval;

    context.clearRect(0, 0, width, height);

    var newRings = rings.map(function (ring) {
        return ring.draw(context).addRadius(delta);
    });

    var now = Date.now();

    setTimeout(loop, next - now, next,
        Math.floor((now - start) / 1000) === rings.length / 2 ?
            [left, right].concat(newRings) : newRings);
}
下面是正在发生的事情:

  • 首先我们清除屏幕
  • 然后我们画出所有的环,增加它们的大小
  • 如果一秒钟过去了,我们将向阵列添加两个新环
  • 最后,我们计算何时再次调用
    循环
    ,以便它在正确的
    间隔
    后触发

  • 请参阅演示:

    我将重写部分代码以启用此功能。例如,我将重写您的
    Ring
    类,如下所示:

    var Ring = defclass({
        constructor: function (x, y, r) {
            this.x = x;
            this.y = y;
            this.r = r;
        },
        draw: function (context) {
            context.beginPath();
            context.arc(this.x, this.y, this.r, 0, Math.PI * 2);
            context.stroke();
            return this;
        },
        addRadius: function (r) {
            return new Ring(this.x, this.y, this.r + r);
        }
    });
    
    function loop(last, rings) {
        var next = last + interval;
    
        context.clearRect(0, 0, width, height);
    
        var newRings = rings.map(function (ring) {
            return ring.draw(context).addRadius(delta);
        });
    
        var now = Date.now();
    
        setTimeout(loop, next - now, next,
            Math.floor((now - start) / 1000) === rings.length / 2 ?
                [left, right].concat(newRings) : newRings);
    }
    
    您的
    类构造函数现在接受
    x
    y
    和半径
    r
    addRadius
    函数返回一个新的
    Ring
    ,而不是对原始环进行变异。这很好,因为不变性使代码更易于使用。噢,
    defclass
    声明为:

    function defclass(prototype) {
        var constructor = prototype.constructor;
        constructor.prototype = prototype;
        return constructor;
    }
    
    然后我们为您的眼睛制作两个戒指:

    var radius = 10;
    var delta = 0.1;
    
    var left = new Ring(cx - (cx / 3.6), cy - 5, radius);
    var right = new Ring(cx + (cx / 3.6), cy - 10, radius);
    
    之后,我们称之为动画循环:

    var interval = 50 / 3;
    var start = Date.now();
    loop(start, [left, right]);
    
    由于我们希望以60 FPS的速度播放,因此间隔为
    1000/60
    ,可以简化为
    50/3
    。动画循环定义如下:

    var Ring = defclass({
        constructor: function (x, y, r) {
            this.x = x;
            this.y = y;
            this.r = r;
        },
        draw: function (context) {
            context.beginPath();
            context.arc(this.x, this.y, this.r, 0, Math.PI * 2);
            context.stroke();
            return this;
        },
        addRadius: function (r) {
            return new Ring(this.x, this.y, this.r + r);
        }
    });
    
    function loop(last, rings) {
        var next = last + interval;
    
        context.clearRect(0, 0, width, height);
    
        var newRings = rings.map(function (ring) {
            return ring.draw(context).addRadius(delta);
        });
    
        var now = Date.now();
    
        setTimeout(loop, next - now, next,
            Math.floor((now - start) / 1000) === rings.length / 2 ?
                [left, right].concat(newRings) : newRings);
    }
    
    下面是正在发生的事情:

  • 首先我们清除屏幕
  • 然后我们画出所有的环,增加它们的大小
  • 如果一秒钟过去了,我们将向阵列添加两个新环
  • 最后,我们计算何时再次调用
    循环
    ,以便它在正确的
    间隔
    后触发

  • 请参阅演示:

    如果没有立即启动,请点击FORK上的刷新。我的浏览器有时会出现代码笔的奇怪故障。等圆圈变大,你就会看到下一个圆圈开始了。天哪!谢谢你,好心的先生!你真了不起。我非常感谢你所做的一切。你帮了我这么多。再次感谢!!:-)我知道我已经谢谢你了,但我真的很感谢你。我喜欢你写这封信的方式。我会记住这一点。不知道为什么我没有想到while循环。谢谢你增加了我的知识。如果叉子不能立即启动,请点击刷新。我的浏览器有时会出现代码笔的奇怪故障。等圆圈变大,你就会看到下一个圆圈开始了。天哪!谢谢你,好心的先生!你真了不起。我非常感谢你所做的一切。你帮了我这么多。再次感谢!!:-)我知道我已经谢谢你了,但我真的很感谢你。我喜欢你写这封信的方式。我会记住这一点。不知道为什么我没有想到while循环。谢谢你增加了我的知识。太棒了!!UGG!对不起,我把答案给了另一个人,但是你的回答太好了!事实上,我非常感谢你花时间解释并写出来。啊,伙计。很抱歉,您没有得到答案。但是非常感谢你的回答。我要检查你们两个的代码。再次,我很抱歉你们并没有得到答案,但它工作得很好。我+1它。谢谢大家!!:-)你做了一些很棒的事情。我不太明白,但就像我在检查之前说的那样。我对三元组和其他东西了解不多,但看到它的实际应用很酷。非常感谢。哦,老兄。太棒了!!UGG!对不起,我把答案给了另一个人,但是你的回答太好了!事实上,我非常感谢你花时间解释并写出来。啊,伙计。很抱歉,您没有得到答案。但是非常感谢你的回答。我要检查你们两个的代码。再次,我很抱歉你们并没有得到答案,但它工作得很好。我+1它。谢谢大家!!:-)你做了一些很棒的事情。我不太明白,但就像我在检查之前说的那样。我对三元组和其他东西了解不多,但看到它的实际应用很酷。非常感谢。我可以试一试吗@马克哈哈哇!太棒了!!!爱是溢出的。这么多有才华的人都愿意帮忙。我可以试一试吗@马克哈哈哇