2017-06-25 4 views
0

私のalbImg配列に画像をロードしています。私のループでjavascript canvas - toDataURL()で作成した画像がロードされているかどうかを確認します。

私は、この操作を行います。

for(var j = 1; j < albImg.length; j++){ 
     if(albImg[j].complete == true && albImg[j].width > 0){ 
      loadedimages++; 
     } 
    } 

すべての私のイメージがロードされていることを確認します。 私は、このように私のflipImg()関数を呼び出します。

if(loadedimages == albImg.length-1){ 
     flipImg(); 
    } 

私は、画像を反転し、私の問題が始まる

ctx2.save(); 
ctx2.scale(-1, 1); 
for (var i = RszSpriteCount; i < sprites.length; i++) { 
    ctx2.drawImage(albImg[sprites[i][0]], sprites[i][1], sprites[i][2], sprites[i][3], sprites[i][4], 0 - (sprites[i][1] + sprites[i][3]), sprites[i][2], sprites[i][3], sprites[i][4]); 
} 
ctx2.restore(); 
var flipSz = albImg.length; 
albImg[flipSz] = new Image(); 
albImg[flipSz].src = cnv2.toDataURL(); 

がここにあります。

私が作成した新しい画像 - albImg [5] - は読み込まれるまで表示できません。 しかし、すでに読み込まれているかのように作成されます。

albImg私はそれを表示する前に、[5] .widthは既に(750に)設定されています。それを言うことです

。 albImg [5] .completeは、表示する前にtrueに設定されています。albImg [5] .onload = ctx.drawImage(albImg [5]、0、0);イメージがロードされる前にイメージを描画しようとします。

フリップしたイメージが表示される前に実際に読み込まれているかどうかを確認するにはどうすればよいですか? Javascriptで? (原因私はこのためにjQueryを使用していない状況に)

助けてください。

+0

なぜ 'イメージがロードされる前に、表示しようonload'でしょうか? 'onload'の呼び出しはイメージがロードされていることを意味します。 – 11thdimension

答えて

2

あなたの主なエラーは、onloadイベントハンドラを設定して行う方法である:

albImg[5].onload = ctx.drawImage(albImg[5], 0, 0) 

onloadリスナーにdrawImage()undefined)の戻り値を設定します。何をしたい

がtrueに設定さcompletewidth性質のために

albImg[5].onload = e => ctx.drawImage(albImg[5], 0, 0); 

または

albImg[5].onload = function(){ ctx.drawImage(this, 0, 0) }; 

ある画像の読み込みは常に非同期である一方であるため、それは、ですあなたの場合、画像は既にHTTPキャッシュされている可能性があります。
HTTP読み込みとJavaScript実行が同じスレッドで実行されないため、ブラウザがそのプロパティを返す前にイメージが実際に読み込まれる可能性があります。

でも、それでもonloadイベントは発生します(ただし、srcの前に設定するのが最適です)。

var cacher = new Image(); 
 
cacher.onload = function(){ 
 
    var img = new Image(); 
 
    img.onload = function(){ 
 
    console.log('"onload" fires asynchronously even when cached'); 
 
    }; 
 
    img.src = c.toDataURL(); 
 
    console.log('cached : ', img.complete, img.naturalWidth); 
 
    } 
 
cacher.src = c.toDataURL(); 
 
console.log('before cache :', cacher.complete, cacher.naturalWidth);
<canvas id="c"></canvas>

新しい画像(HTMLマークアップではないもの)を取り扱う際に、常に単にそのonloadイベントに耳を傾けます。


さて、あなたはあなたの質問に与えたいくつかの情報と、あなたがするので、でもこれらのイメージを必要としない、また(当然のスプライトを除く)は、その負荷のいずれかに対処するように思わ直接かつ同期してctx.drawImage(CanvasElement, x, y)に電話することができます。

const ctx = c.getContext('2d'); 
 
ctx.moveTo(0, 0); 
 
ctx.lineTo(300, 75); 
 
ctx.lineTo(0, 150); 
 
ctx.fillStyle = 'rgba(120,120,30, .35)'; 
 
ctx.fill(); 
 

 
const flipped = c.cloneNode(); // create an offscreen canvas 
 
const f_ctx = flipped.getContext('2d'); 
 
f_ctx.setTransform(-1, 0,0,1, c.width, 0);// flip it 
 
f_ctx.drawImage(c,0,0);// draw the original image 
 

 
// now draw this flipped version on the original one just like an Image. 
 
ctx.drawImage(flipped, 0,0); 
 
// again in 3s 
 
setTimeout(()=>ctx.drawImage(flipped, 150,0), 3000);
<canvas id="c"></canvas>

+0

私はあなたのおかげでそれを解決しました。 これを将来見る人には: コードを追加しても機能しませんでしたが、キャンバスに描画されている画像もtoDataUrl()によって生成されていました。その絵は、私の2番目のイメージに基づいたキャンバスに必ずしも読み込まれませんでした。 空白のキャンバス=空の画像。 しかし、最初のイメージでオンロードを実装することで問題は解決しました。今度は画像が常にロードされ、ロードされた画像は常に反転した画像を含みます。 –

+0

そして私が最初にイメージにロードする理由は、ループごとに数回ではなく1回だけイメージを反転することで、処理能力を節約し、バッテリ使用量を減らすことができるからです(モバイルアプリケーション用です)。 それは意味がありますか?たぶん私はそれを思ってしまったかもしれない。 –

+1

@DanielBengtsson、それは理にかなっていますが、それは最良の方法ではありません。実際に画像(またはそのキャンバスとして機能するキャンバス)を反転するだけの場合は、表示されるキャンバスの変換マトリックスを変更してdrawImageを使用するだけでメモリを消費しません。それが完全なコンポジションであれば、オフスクリーンのキャンバスを使用する方がいいでしょう(私が答えていたように)、このオフスクリーンキャンバスへの参照を保持してください。イメージへの変換は、常にメモリのために重いです。ブラウザは、ファイルのb64ストリング表現+デコードされたイメージを保持する必要があります。 – Kaiido

関連する問題