【问题标题】:forcing canvas update强制画布更新
【发布时间】:2012-05-15 20:42:04
【问题描述】:

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

编辑:

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

我该怎么办? :)

【问题讨论】:

  • 和你的代码?如果没有一些示例代码,我们怎么知道你是如何绘制的。
  • 我已经为你编辑了一个示例脚本:)

标签: javascript html canvas


【解决方案1】:

在执行较长任务之前,您可以做的另一件事是让画布显示在短暂的超时后开始 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

【讨论】:

  • 被接受为答案 - 简单而有效,只需延迟一点,画布就有机会更新,非常适合单个静态加载屏幕 - 谢谢 :)
【解决方案2】:

如果我的理解正确,没有办法像在 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 线程总是忙于你的 5 秒循环。它从来没有时间更新 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>

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

如果您需要任何说明,请告诉我!

【讨论】:

  • 不是我所追求的,但仍然很有趣 - 感谢您提供信息!
  • 出色的答案,我从中学到了很多!在这种情况下,我选择了下面的 setTimeout() 方法,因为它是最简单的加载方式(生成大量程序数据、加载精灵、初始化数据库等!),但我也投了赞成票,因为我认为它非常相关和有用。我很感谢你的时间:)
  • 别担心!感谢您的反馈! :)
猜你喜欢
  • 2011-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多