簡體   English   中英

如何將內容從隱藏的畫布復制到可見的畫布?

[英]How to copy content from hidden canvas to visible canvas?

將畫布從緩沖畫布復制到頁面上的畫布時遇到一些困難。 到目前為止,我已經構建了一個Render對象,一個Level對象,並且我有主游戲循環(當前只是一個啟動功能)。

我能夠很好地在Render對象中寫入緩沖畫布(如果我添加了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);

請注意,Renderer在一個單獨的文件中,並使用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%是演示: http : //jsbin.com/upatij/edit#javascript,html,live

壞消息:這意味着您的級別代碼中的某些內容已損壞,因為我的存根級別代碼可以在您的框架中正常工作... :-(

存根級別:

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()函數實際上是一個異步“加載”。 不幸的是,您當前的概念化無效。 您的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游戲編程有些棘手,因為您實際上必須拋出“ Loading ...”微調框,並避免進入渲染循環,直到所有“資源”都加載完畢。 實際上,您需要“就緒”的概念,例如。 Load(fOnReady)Draw(ctx)而不是asyncDraw(ctx, fOnReady) ...

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

希望這對您有幫助-ck

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM