如何将隐藏画布中的内容复制到可见画布?

发布于 2025-01-07 01:30:01 字数 1199 浏览 5 评论 0原文

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

我可以很好地写入渲染对象中的缓冲区画布(如果我添加 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); };
    };
}

I am having some difficulty copying a canvas from my buffer canvas to the canvas on my page. Thus far I have built a Render object, a Level object, and I have my main game loop (currently just a launch function).

I am able to write to the buffer canvas in the Render object just fine (if I add a document.body.append() statement the canvas successfully appends to the document with the necessary content) but I cannot copy from the buffer canvas to my main canvas. See below for a snippet of my code:

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);

Note that Renderer is in a separate file and is loaded using the script tags in my HTML page.

As mentioned earlier, the drawToCanvas() function doesn't appear to successfully copy data from one canvas to another. Appending my source canvas confirms that it contains the expected data.

edit: I have listed my level code below.

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

守不住的情 2025-01-14 01:30:01

我有好消息,也有坏消息。

好消息是您在此处显示的代码 100% 有效
这是演示: http://jsbin.com/upatij/edit#javascript,html, 坏消息

:这意味着您的 Level 代码中的某些内容已损坏,因为我的存根 Level 代码在您的框架中完美运行... :-(

存根 Level:

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();
  };
}

祝您好运! -ck

在你之后查看您的关卡代码:

问题是同步性之一,您在这里使用的类通过欺骗性命名向您隐藏了问题,因为您的 Level.Draw 根本不是绘图函数。 .. 让我为您解开它:

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

// var render = new Renderer(c.width, c.height);
var Renderer_c = document.createElement('canvas');
var Renderer_ctx = Renderer_c.getContext('2d');
document.body.appendChild(Renderer_c); //added to show
Renderer_c.width = c.width;
Renderer_c.height = c.height;

// var level1 = new Level('images/imagequality.png');
var map = new Image();
document.body.appendChild(map); //add to show
map.src = 'http://th06.deviantart.net/fs71/150/i/2011/255/9/5/omnom_upside_down_by_earnurm-d49pjnl.png';

console.log('at ' + 1);
// level1.Draw(render.getBufferContext());
map.onload = function() { 
  console.log('at ' + 3);
  //this happens async:
  alert('drawing now!');
  Renderer_ctx.drawImage(map,0,0); 
};

console.log('at ' + 2);
// render.drawToCanvas(ctx);
ctx.drawImage(Renderer_c, 0, 0);

如果您运行该代码,您将看到在调用 onload 时,其他所有内容都已执行,您会注意到控制台将如何读取:

at 1 
at 2
at 3

以及因此,此时此刻alert('drawing now!'); 已执行...

// render.drawToCanvas(ctx);
ctx.drawImage(Renderer_c, 0, 0);

将已经运行...基本上,您的 Draw() 函数实际上是异步“Load”。 ,你目前的概念化不起作用。您的 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) AND Draw(ctx) 而不仅仅是 asyncDraw(ctx, fOnReady)...

更新后的 jsbin 在这里:http://jsbin.com/upatij/2/edit

希望这有帮助 -ck

I have good news, and I have bad news.

The good news is the code you show here works 100%
here is the demo: http://jsbin.com/upatij/edit#javascript,html,live

bad news: that means that something inside your Level code is broken as my stub Level code works perfectly in your framework... :-(

stub Level:

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();
  };
}

good luck! -ck

AFTER YOUR SEEING YOUR LEVEL CODE:

The problem is one of synchronicity, your use of classes here are hiding the problem from you, via deceptive naming, as your Level.Draw, is not a draw function at all... let me unwrap it for you:

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

// var render = new Renderer(c.width, c.height);
var Renderer_c = document.createElement('canvas');
var Renderer_ctx = Renderer_c.getContext('2d');
document.body.appendChild(Renderer_c); //added to show
Renderer_c.width = c.width;
Renderer_c.height = c.height;

// var level1 = new Level('images/imagequality.png');
var map = new Image();
document.body.appendChild(map); //add to show
map.src = 'http://th06.deviantart.net/fs71/150/i/2011/255/9/5/omnom_upside_down_by_earnurm-d49pjnl.png';

console.log('at ' + 1);
// level1.Draw(render.getBufferContext());
map.onload = function() { 
  console.log('at ' + 3);
  //this happens async:
  alert('drawing now!');
  Renderer_ctx.drawImage(map,0,0); 
};

console.log('at ' + 2);
// render.drawToCanvas(ctx);
ctx.drawImage(Renderer_c, 0, 0);

If you run that code you will see that at the moment at which onload is called everything else has already executed, you'll notice how the console will read:

at 1 
at 2
at 3

and as such, at the moment when alert('drawing now!'); is executed...

// render.drawToCanvas(ctx);
ctx.drawImage(Renderer_c, 0, 0);

will have already run... Basically your Draw() function is actually an asynchronous "Load". Unfortunately, you current conceptualization does not work. Your Draw() function needs to be an async one like this:

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();
        };
    };
}

and the function should then be called like this in your example:

level1.asyncDraw(render.getBufferContext(), function() {
  render.drawToCanvas(ctx);
});

I should probably go on to say that this type of asynchronisity makes HTML5 game programming a little tricky as you really have to throw up the "Loading..." spinner and refrain from going into your rendering loop until all "resources" have loaded. In all practicality you need the concept of "ready" eg. Load(fOnReady) AND Draw(ctx) instead of just asyncDraw(ctx, fOnReady)...

the updated jsbin is here: http://jsbin.com/upatij/2/edit

hope this helps -ck

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文