强制画布更新

时间:2012-05-15 09:27:04

标签: javascript html5 canvas

有没有办法强制画布更新?我想显示加载消息,但游戏会在显示之前锁定加载。在调用加载函数之前,我觉得我需要告诉画布“现在画画”,但也许还有另一种方式......

编辑:

好吧,为了清楚我已经写了一个非常小的脏脚本(我最好能在我的茶歇中做到:P)来展示我想要过来的东西。这里:

<html>
<head>
    <title>test page</title>
</head>

<body onload="init();">
    <canvas id="cnv" width="300" height="300">
        canvas not supported.<br/>
    </canvas>
</body>
</html>

<script type="text/javascript">  

    var ctx;

        function init()
    {
        var canvas = document.getElementById('cnv');
        ctx = canvas.getContext('2d');

        ctx.fillStyle = "rgb(255, 0, 0)";
        ctx.fillRect(0,0,300,300);

        FakeLoad();

        ctx.fillStyle = "rgb(0, 255, 0)";
        ctx.fillRect(0,0,300,300);
    }

    function FakeLoad()
    {
        var d = new Date();
        var start = d.getTime();

        while (new Date().getTime() - start < 5000)
        {
            //emulate 5 secs of loading time
        }
    }
</script>

现在的想法是脚本应该绘制一个红色方块以显示其“加载”和完成后的绿色方块。但是如果你将它复制到一个html文件中,你会看到暂停5秒然后绿色出现,从不出现红色。在我脑海里,我想要一些像ctx.Refresh();我画绿色方块后告诉它“现在更新!不要等!”但从回答来看,这不是解决问题的方法。

我该怎么办? :)

2 个答案:

答案 0 :(得分:5)

在执行较长任务之前允许画布显示的另一件事是在短暂超时后开始FakeLoad:

    var canvas = document.getElementById('cnv');
    ctx = canvas.getContext('2d');

    ctx.fillStyle = "rgb(255, 0, 0)";
    ctx.fillRect(0,0,300,300);

    setTimeout(function() {
      FakeLoad();

      ctx.fillStyle = "rgb(0, 255, 0)";
      ctx.fillRect(0,0,300,300);
    }, 20); // 20 ms - should be enough to draw something simple

答案 1 :(得分:2)

如果我理解正确,就无法像在WPF中重新渲染/绘制或重新流动HTML DOM一样更新画布。

这是因为画布使用中间模式图形。从本质上讲,画布唯一保留知识的是构成画布的像素。当你调用draw rect或draw line时,组成矩形或直线的像素被添加到画布中,就画布而言,它会忘记绘制rect或绘制圆形调用的所有内容,因此我们无法刷新画布得到相同的结果。

如果你正在寻找“保留”渲染图形的知识的东西,你可以尝试SVG,这使用保留模式图形。基本上它有自己的DOM(对象的heirachy(圆形,矩形等)),每次区域变脏时都会重新渲染。

简而言之,此页面非常适合帮助您了解即时模式图形和保留模式图形之间的区别:http://msdn.microsoft.com/en-us/library/ie/gg193983(v=vs.85).aspx

所有这一切,如果我误解了你的问题,请接受我的道歉!

<强>更新

根据问题中的额外信息,

你永远不会看到绿色方块的原因是因为主javascript线程总是忙于你的五秒循环。它永远不会有任何时间来更新UI。为了让您的加载屏幕有时间更新画布,您需要异步进行所有加载。

你会做什么样的装载?如果是图片等,您可以使用$.ajaxjQuery抓取它们。这将从其位置异步获取图像,一旦检索到最后一个图像,您就可以使用您的内容清除并重新绘制画布。

我猜是这样的:

<script type="text/javascript">  

    var ctx;

    function init()
    {
        var canvas = document.getElementById('cnv');
        ctx = canvas.getContext('2d');

        ctx.fillStyle = "rgb(255, 0, 0)";
        ctx.fillRect(0,0,300,300);

        FakeLoad(); 
    }

    function FakeLoad()
    {
        $.ajax({
          url: "www.foo.com/bar.jpg",
          success: function(data)
          {
              // Do something with the data (persist it)
              RenderApp();
          }
        });
    }

    function RenderApp()
    {
        // Rendering the rest of the application / game
        ctx.fillStyle = "rgb(0, 255, 0)";
        ctx.fillRect(0,0,300,300);
    }

</script>

显然这有点像psudo-code,但希望它会给你一些想法!

如果您需要任何澄清,请与我们联系!