LoginSignup
1
1

More than 1 year has passed since last update.

js canvas画像と図形を連射して表示されないときのオチ

Last updated at Posted at 2021-09-18

Screenshot from 2021-09-18 16-04-02.png

要約

結論からいうと画像の読み込みは一瞬では終わらないのでonload後に描くよう意識しないとダメよってだけの話です。

問題

画像を表示させてその裏側に円を付けたいと思った私がいます。画像はcanvasのdrawImage()で、円はcanvasのarc()で描きます。しかし、これを正直に書くだけではループして連発する際に上手く行かないんですね。これの解決策を備忘録で残します。

問題のコード

  const canvas=document.createElement("canvas");
    canvas.width = 600;
    canvas.id = "FieldCanvas";
    canvas.height = 400;
    const ctx = canvas.getContext("2d");
 document.getElementById("main").appendChild(canvas);
//ここまでキャンバスを用意するための前置き
  ctx.beginPath();   
    for(let yoko=0;yoko<10;yoko++){
          let img=new Image(15,15);
          img.src="./imgbox/magicCamp.svg";
          ctx.arc(yoko*15*2+15,15,15,0,2*Math.PI);
          ctx.fill();
          ctx.drawImage(img,yoko*15*2,0,30,30);
          }
   ctx.closePath();

出力1 画像が描かれない

Screenshot from 2021-09-18 16-05-01.png

赤い魔法陣の画像も現れるはずなんだが、.arc()で描いた緑円しかない。drawImageは完全に忘れ去られているようだ。。

解決方法

画像読み込みができてないのにfor文が次の描画に走ってしまうからdrawImageが無視されてしまっている模様。ならば.onloadイベントを用意すれば良いのでは?

//描画部分のみ
 ctx.beginPath();   
 var img=new Image(15,15);
   for(let yoko=0;yoko<10;yoko++){
         img.src="./imgbox/magicCamp.svg";
         ctx.arc(yoko*15*2+15,15,15,0,2*Math.PI);
         ctx.fill();
           img.onload=()=>{
           ctx.drawImage(img,yoko*15*2,0,30,30);
           }
         }
   ctx.closePath();

ちなみにfor文の「let yoko」をvarで宣言すると円は正常に出るが、画像は全て最後のyoko座標で出るので、忘れるなよ私。。

出力2 画像も一緒に載る

Screenshot from 2021-09-18 16-04-02.png

もう少し安定的な策

画像の描画は「onload」完了後にする、でとりあえず解決なのだが、そこそこ複雑なコードで組んでみると再び表示が不安定になることがあった。当時はonloadの発火の後で円も含めて全ての描画をするように変更したら上手くいったが原因はよくわからない。この辺について、詳しくなったら追記したいと思う。

//onload()の中に画像以外の描画処理もまとめる。こっちのほうがましか?
 for(let yoko=0;yoko<10;yoko++){
       var img=new Image();
        img.src="./imgbox/magicCamp.svg";
        img.onload=()=>{
           ctx.fillStyle="#ff6";
           ctx.beginPath();
           ctx.arc(yoko*15*2+15,15,15,0,2*Math.PI);
           ctx.fill();
           ctx.closePath();    
           ctx.drawImage(img,yoko*15*2,0,30,30);
        }
 }
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1