Javascript 如何将内容从隐藏画布复制到可见画布?

Javascript 如何将内容从隐藏画布复制到可见画布?,javascript,html,canvas,Javascript,Html,Canvas,我在将画布从缓冲区画布复制到页面上的画布时遇到一些困难。到目前为止,我已经构建了一个渲染对象,一个关卡对象,并且我有我的主游戏循环(目前只是一个启动函数) 我能够在渲染对象中写入缓冲区画布(如果我添加了document.body.append()语句,画布会成功地将必要的内容附加到文档),但我无法从缓冲区画布复制到主画布。请参阅下面的代码片段: function Renderer(bufferWidth, bufferHeight) { var c=document.createElem

我在将画布从缓冲区画布复制到页面上的画布时遇到一些困难。到目前为止,我已经构建了一个渲染对象,一个关卡对象,并且我有我的主游戏循环(目前只是一个启动函数)

我能够在渲染对象中写入缓冲区画布(如果我添加了document.body.append()语句,画布会成功地将必要的内容附加到文档),但我无法从缓冲区画布复制到主画布。请参阅下面的代码片段:

function Renderer(bufferWidth, bufferHeight) {
    var c=document.createElement('canvas');
    var ctx=c.getContext('2d');
    c.width=bufferWidth;
    c.height=bufferHeight;

    this.getBufferContext = function() { return ctx; };
    this.getBufferElement = function() { return c; };

    this.drawToCanvas = function(canvasCtx) { 
        canvasCtx.drawImage(c,0,0);
    };
}


var c = document.getElementById('mycanvas');
var ctx = c.getContext('2d');

var render = new Renderer(c.width, c.height);   
var level1 = new Level('images/imagequality.png');

level1.Draw(render.getBufferContext());
render.drawToCanvas(ctx);
请注意,渲染器位于单独的文件中,并使用“我的HTML”页面中的脚本标记加载

如前所述,drawToCanvas()函数似乎无法成功地将数据从一个画布复制到另一个画布。附加“我的源画布”可确认它包含预期的数据

编辑:我在下面列出了我的级别代码

function Level(mapname) {
    var map=new Image();
    map.src=mapname;

    this.Draw = function(renderer) {
        map.onload = function() { renderer.drawImage(map,0,0); };
    };
}

我有好消息,也有坏消息

好消息是你在这里展示的代码100%有效 以下是演示:

坏消息:这意味着您的级别代码中的某些内容被破坏,因为我的存根级别代码在您的框架中可以完美地工作…:-(

存根级别:

function Level() {
  this.Draw = function(xxctx) {
    for (var i = 0; i < 30; i++) {
      xxctx.moveTo(10 + (i * 40 % 300), 10 + (parseInt(i / 6, 10) * 40));
      xxctx.lineTo(40 + (i * 40 % 300), 40 + (parseInt(i / 6, 10) * 40));
      xxctx.moveTo(40 + (i * 40 % 300), 10 + (parseInt(i / 6, 10) * 40));
      xxctx.lineTo(10 + (i * 40 % 300), 40 + (parseInt(i / 6, 10) * 40));
    }
    xxctx.stroke();
  };
}
如果运行该代码,您将看到在调用
onload
时,其他所有操作都已执行,您将注意到控制台将如何读取:

at 1 
at 2
at 3
因此,在执行
警报('drawing now!');

// render.drawToCanvas(ctx);
ctx.drawImage(Renderer_c, 0, 0);
将已经运行…基本上您的
Draw()
函数实际上是一个异步“加载”。不幸的是,您当前的概念化不起作用。您的
Draw()
函数需要是一个异步函数,如下所示:

function Level(mapname) {
    var map=new Image();
    document.body.appendChild(map); //add to show
    map.src=mapname;

    this.asyncDraw = function(renderer, onComplete) {
        map.onload = function() { 
          renderer.drawImage(map,0,0); 
          onComplete();
        };
    };
}
然后,在您的示例中,应该像这样调用函数:

level1.asyncDraw(render.getBufferContext(), function() {
  render.drawToCanvas(ctx);
});
我可能应该继续说,这种类型的异步性使得HTML5游戏编程有点棘手,因为你真的必须扔掉“加载…”微调器,在所有“资源”加载之前不要进入渲染循环。在所有实践中,你都需要“就绪”的概念,例如
Load(fOnReady)
Draw(ctx)
而不仅仅是
asyncDraw(ctx,fOnReady)

更新后的jsbin如下:


希望这有帮助-ck

感谢您的反馈。如果您感兴趣,我已将我的级别代码附加到原始文件中。那里没有发生什么特别的事情…到目前为止,它只是在提供的画布上下文(渲染器)中绘制单个图像。FWIW我有绘图代码(创建上下文、渲染器、级别等)在名为launch()的函数中,我在HTML页面的body.onload函数中调用了该函数。
level1.asyncDraw(render.getBufferContext(), function() {
  render.drawToCanvas(ctx);
});