3

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

编辑:

好的,为了清楚起见,我写了一个非常小的脏脚本(我可以在茶歇时做的最好的事情: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(); 在我画出绿色方块告诉它“现在更新!不要等待!”之后 但从回复来看,这不是处理问题的方法。

我应该怎么办?:)

4

2 回答 2

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
于 2012-05-15T12:42:04.500 回答
3

如果我对您的理解正确,则无法以与您可以在 WPF 中重新渲染/绘制或重新流动 HTML DOM 相同的方式更新画布。

这是因为画布使用中间模式图形。本质上,画布唯一保留知识的是构成画布的像素。当您调用 draw rect 或 draw line 时,构成矩形或线条的像素被添加到画布中,就画布而言,它忘记了所有关于 draw rect 或 draw circle 调用,因此我们无法刷新画布并得到相同的结果。

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

总之,这个页面非常适合帮助你理解即时模式图形和保留模式图形的区别: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>

显然这是一种伪代码,但希望它能给你一些想法!

如果您需要任何澄清,请告诉我!

于 2012-05-15T10:14:14.200 回答