【问题标题】:Animating HTML canvas elements动画 HTML 画布元素
【发布时间】:2011-12-01 22:15:21
【问题描述】:

我正在尝试为 <canvas> 上的元素设置动画,但 setTimeout 和 setInterval 给我带来了问题。我的数据在一个数组中。我知道它的长度。对于每个节点,我生成一个 X 和一个 Y、一个基本方向和一个颜色。然后我的绘图函数为每个节点绘制一个圆圈。

当我尝试使用 setInterval 循环时,我的问题就出现了。我的想法是,我可以建立所有 X、Y 值,然后循环返回并每 10ms-100ms 递增它们。但是每次我使用 setInterval 时,保存每个圆的数据的子数组的长度都为 3,并且值设置为未定义。

我曾经使用各种对象对此进行了编码,但无法使动画正常工作。我了解了在对象中设置范围 setInterval() 的问题。我在没有建立一堆对象的情况下对其进行了重新编码。仍然没有运气。

$(document).ready(function(){
    getTweets();
});

CTX = $('#tweets')[0].getContext("2d");
WIDTH = $('#tweets').width();
HEIGHT = $('#tweets').height();
RADIUS = 10;
TWEETS = [];
CORDS = [];
DIRECTION = ['north','east','south','west'];

function getTweets(){
    $.getJSON("http://search.twitter.com/search.json?callback=?&q=scion&rpp=100",
    function(r){
        var numberOfTweets = r.results.length;
        while(numberOfTweets--){
            TWEETS.push(r.results[numberOfTweets].text);
        }
        plotXY();
        animateTweets()
    });
}

function animateTweets(){
    return setTimeout(plotXY(true),100);
}

function plotXY(animating){
    if(!animating){
        var numberOfTweets = TWEETS.length;
        while(numberOfTweets--){
            var topY = Math.ceil(Math.random()*(HEIGHT-20)),
                leftX = Math.ceil(Math.random()*(WIDTH-20)),
                cardinal = Math.floor(Math.random()*4),
                color = '#'+Math.floor(Math.random()*16777215).toString(16);

            var valCords = validateCords(leftX, topY);
            CORDS.push([valCords[0], valCords[1], cardinal, color]);
        }
        // console.log('animating false');
        // console.log(CORDS);
    }
    else{
        var numberOfTweets = TWEETS.length;
        while(numberOfTweets--){
            if(CORDS[numberOfTweets][2]=='north'){ //NORTH
                CORDS[numberOfTweets][1]+=2;
                CORDS[numberOfTweets][0]+=2;
            }
            if(CORDS[numberOfTweets][2]=='east'){ //EAST
                CORDS[numberOfTweets][1]+=2;
                CORDS[numberOfTweets][0]-=2;
            }
            if(CORDS[numberOfTweets][2]=='south'){ //SOUTH
                CORDS[numberOfTweets][1]-=2;
                CORDS[numberOfTweets][0]-=2;
            }
            if(CORDS[numberOfTweets][2]=='west'){ //WEST
                CORDS[numberOfTweets][1]-=2;
                CORDS[numberOfTweets][0]+=2;
            }

            var valCords = validateCords(leftX, topY, numberOfTweets);

            CORDS.push([valCords[0],valCords[1],cardinal]);
            CORDS.shift();          
        }
        // console.log('animating true');
        // console.log(CORDS);
    }
    drawCircles();
}


function drawCircles(){
    console.log('drawing');
    var numOfCords = CORDS.length;
    clear();

    while(numOfCords--){
        CTX.fillStyle = CORDS[numOfCords][3];
        CTX.beginPath();
        CTX.arc(CORDS[numOfCords][0], CORDS[numOfCords][1], RADIUS, 0, Math.PI*2, true);
        CTX.closePath();
        CTX.fill();
    }
}

【问题讨论】:

  • 您是否将数组存储在像窗口对象这样的持久位置?
  • 这是一个问题:setTimeout(plotXY(true),100); - 调用plotXY(true),然后将结果传递给setTimeout。你需要做的是传递一个函数的引用,最简单的方法是这样的:setTimeout(function(){plotXY(true);}, 100);(同样适用于setInterval()。你可能想在@结束时再次调用setTimeout() 987654329@函数,或者使用setInterval(),否则你的动画只有一步。(注意:如果你的函数没有任何参数,你可以像这样直接传递它:setTimeout(plotXY,100)。)
  • @nnnnnn 感谢您指出我的格式错误。我有 setInterval 但用 setTimeout 替换它,看看它是否只是计时功能的问题。我认为这是基于您的建议。我现在必须进行 fe 更改,但我认为它可能解决了我的问题。
  • 在这种情况下,我将添加我的评论作为答案......

标签: javascript animation html5-canvas setinterval


【解决方案1】:

我不知道这是否是您代码中的唯一问题,但一个重要问题是您使用setTimeout() 的方式:

setTimeout(plotXY(true), 100); // doesn't work

也就是说调用plotXY() 函数,然后将它返回的任何内容作为第一个参数传递给setTimeout

相反,setTimeout() 的第一个参数应该是函数表达式或对函数的引用,如下所示:

setTimeout(plotXY, 100);      // works, but doesn't pass parameter to plotXY()

请注意,plotXY 没有为此目的使用括号。但是当然这会给您带来另一个问题:您希望使用参数true 调用plotXY()。这很容易解决,只需将对 plotXY() 的调用包装在另一个函数中并将该另一个函数传递给 setTimeout()

setTimeout(function(){ plotXY(true); }, 100);     // works

这会创建一个匿名函数并将该函数传递给setTimeout()

您可能想在您的plotXY() 函数结束时再次调用setTimeout(),或者使用setInterval(),否则您的动画将只有一步。或者您可以执行以下操作,它显示了解决参数传递问题的另一种方法以及使用setTimeout() 继续调用函数的方法:

function plotXYProxy() {
   plotXY(true);
   setTimeout(plotXYProxy, 100);
}
plotXYProxy();

当然你可以在plotXYProxy()中添加一些条件处理来决定是否设置每个超时,例如,你可以让plotXY()返回一个关于动画是否完成的布尔值,并根据是否调用setTimeout()那个布尔值。或任何适合的。

我刚才所说的setTimeout()的参数也适用于setInterval()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-16
    • 2016-08-23
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    • 2017-05-03
    • 2014-04-20
    相关资源
    最近更新 更多