drawImageの描画順序の指定について

このQ&Aのポイント
  • drawImageメソッドを使用し、Canvasへ画像を描画するプログラムを作成しています。画像は全部3枚あり、座標をずらしてすべて重ねて表示します。
  • 現在のコーディングですと、指定した描画順序のとおりに描画されません。複数の画像に対してonloadを使用しており、画像の読み込みが完了した順番に描画されているような気がします。指定したとおりに描画できる方法はないでしょうか?
  • 描画順序を選択してCanvasに描画するプログラムを作成していますが、指定した描画順序通りの表示ができません。onloadを使用して画像の読み込み完了を待ってから描画しているため、順番通りに表示されないようです。対処方法を教えてください。
回答を見る
  • ベストアンサー

drawImageの描画順序の指定について

いつもお世話になっております。 drawImageメソッドを使用し、Canvasへ画像を描画するプログラムを作成しています。 画像は全部3枚あり、座標をずらしてすべて重ねて表示します。 画像のファイルサイズはすべて異なります。 画像描画のタイミングは選択中のセレクトボックスの項目に変更があった場合です。 この際、フォームの情報によって描画順序を決定します。 本題ですが、現在のコーディングですと、指定した描画順序のとおりに描画されません。 複数の画像に対してonloadを使用しており、画像の読み込みが完了した順番に描画 されているような気がします。指定したとおりに描画できる方法はないでしょうか? ・html <canvas id=main width=160 height=160 style=border:1px solid gray></canvas> <form> <hr> 描画順序 <select name=order onChange=Main(this.form)> <option value=0>1,2,3</p> <option value=1>1,3,2</p> <option value=2>2,1,3</p> <option value=3>2,3,1</p> <option value=4>3,1,2</p> <option value=5>3,2,1</p> </select> </form> ・外部ファイル(js) function Main(f) { var canvas = document.getElementById('main'); if (!canvas || !canvas.getContext) { return false; } var Canvas = canvas.getContext('2d'); Canvas.clearRect(0, 0, 320, 240); var Image1 = new Image(); var Image2 = new Image(); var Image3 = new Image(); if (f.order.value == 0) { Image1.onload = function() { Canvas.drawImage(Image1, 0, 0); } Image2.onload = function() { Canvas.drawImage(Image2, 20, 20); } Image3.onload = function() { Canvas.drawImage(Image3, 40, 40); } Image1.src = GetImageFileName(1); Image2.src = GetImageFileName(2); Image3.src = GetImageFileName(3); } else if (f.order.value == 1) { Image1.onload = function() { Canvas.drawImage(Image1, 0, 0); } Image3.onload = function() { Canvas.drawImage(Image3, 20, 20); } Image2.onload = function() { Canvas.drawImage(Image2, 40, 40); } Image1.src = GetImageFileName(1); Image3.src = GetImageFileName(3); Image2.src = GetImageFileName(2); } else if (f.order.value == 2) { Image2.onload = function() { Canvas.drawImage(Image2, 0, 0); } Image1.onload = function() { Canvas.drawImage(Image1, 20, 20); } Image3.onload = function() { Canvas.drawImage(Image3, 40, 40); } Image2.src = GetImageFileName(2); Image3.src = GetImageFileName(3); :(以降省略) よろしくお願いいたします。

  • y3k
  • お礼率90% (48/53)

質問者が選んだベストアンサー

  • ベストアンサー
  • yyr446
  • ベストアンサー率65% (870/1330)
回答No.2

それぞれのImageのonloadのイベントハンドラーで、すぐにCanvas.drawImageするのではなく、イベントハンドラー内でいったんImageたちを別の格納用配列Imagesにしまっておきます。そして、Imagesの格納数が3以上になっていれば、drawImageの処理を行うってのはどうでしょうか。  var Image1 = new Image();  var Image2 = new Image();  var Image3 = new Image();  Image1.src = GetImageFileName(1);  Image2.src = GetImageFileName(2);  Image3.src = GetImageFileName(3);  x = f.order.value //グローバルスコープ  Image1.onload = function() {   Images[1] = Image1;   if(Images.length >=3 ) draw(x);  }  Image2.onload = function() {   Images[2] = Image2;   if(Images.length >=3 ) draw(x);  }  Image3.onload = function() {   Images[3] = Image3;   if(Images.length >=3 ) draw(x);  }  function draw(x){ switch(x){   case "0":    Canvas.drawImage(Images[1], 0, 0);    Canvas.drawImage(Images[2], 20, 20);    Canvas.drawImage(Images[3], 40, 40);   break;   case "0":   ..............   }  }

y3k
質問者

お礼

ご回答ありがとうございます。 Image3がいちばん最初にロードされた場合、その時点で Images.lengthは3以上になってしまいます。 そのため、カウンタを設け、ロードが完了すればカウントアップ するようにしたところ、きちんと表示されました。 ブラウザは、firefox、opera、chrome、safariと、 excanvas.jsをロードしたIEにて確認を行いましたが、 いずれも問題ありませんでした。 ありがとうございました。

その他の回答 (1)

回答No.1

一部端折ったりしてますが、少し書き足して、Main()の中のImage1,2,3の変数を外に出しました。canvasに描画されてるかどうかは別として、これで画像のプリロードはOKかなと思います。ポイントはinit()です。 <script> var Image1 = new Image(); var Image2 = new Image(); var Image3 = new Image(); // プリロード用 function init() { Image1.src = 'photo01.jpg'; Image2.src = 'photo02.jpg'; Image3.src = 'photo03.jpg'; var bodyTag = document.body; var div = document.createElement('div'); div.style.display = 'none'; div.appendChild( Image1 ); div.appendChild( Image2 ); div.appendChild( Image3 ); bodyTag.appendChild( div ); } init(); // -------------------------------- function Main( f ) { var canvas = document.getElementById('main'); if (!canvas || !canvas.getContext) { return false; } var Canvas = canvas.getContext('2d'); Canvas.clearRect(0, 0, 320, 240); if( f.order.value == 0 ) { // -------------------------------- Image1.onload = function() { Canvas.drawImage(Image1, 0, 0); } // -------------------------------- Image2.onload = function() { Canvas.drawImage(Image2, 20, 20); } // -------------------------------- Image3.onload = function() { Canvas.drawImage(Image3, 40, 40); } // -------------------------------- Image1.src = GetImageFileName(1); Image2.src = GetImageFileName(2); Image3.src = GetImageFileName(3); } else if (f.order.value == 1) { Image1.onload = function() { Canvas.drawImage(Image1, 0, 0); } Image3.onload = function() { Canvas.drawImage(Image3, 20, 20); } Image2.onload = function() { Canvas.drawImage(Image2, 40, 40); } Image1.src = GetImageFileName(1); Image3.src = GetImageFileName(3); Image2.src = GetImageFileName(2); } } // -------------------------------- // -------------------------------- function GetImageFileName( val ) { switch( val ) { case 1: return 'photo01.jpg'; break; case 2: return 'photo02.jpg'; break; case 3: return 'photo03.jpg'; break; } } </script>

y3k
質問者

お礼

ご回答ありがとうございます。 あらかじめ画像を読み込んでおくということですね。

関連するQ&A

  • javascriptで困っています。教えてください

    html5でcanvasに描いた画像をsave_buttonを押してlocalStorageで保存して、それをload_buttonをおして読み込もうとしているのですが、うまくいきません。 canvas.toDataURL();でデータを6bit毎に分割できています。 それを保存して、 var base64 = window.localStorage.getItem("saveKey");で読み込むこともできています。 その後canvasに描画できません。 よろしくお願いします。 var canvas = document.getElementById("myCanvas"); $("#save_button").click(function () {    // Canvasからbase64エンコーディングされた画像データを取得する var canvas = document.getElementById("myCanvas"); var base64 = canvas.toDataURL(); // LocalStorageに保存する window.localStorage.setItem("saveKey", base64); }); $("#load_button").click(function () { // LocalStroageからデータを取得する var base64 = window.localStorage.getItem("saveKey"); // Imageオブジェクトを作成し、src属性にデータを設定する var image = new Image(); image.src = base64; image.onload = function(){ // 画像の読み込みが終わったら、Canvasに画像を反映する。 canvas.drawImage(image, 0, 0); } });

  • 複数選択した画像のキャンバスへの描画につい

    HTML5のタグを <input type="file" id="fileInput" multiple /> として、 ファイル選択のonchageイベントで、 選択した画像をキャンバスに50pxずつずらして描画しようとしたところ、 選択ファイルが2つまでなら、うまく描画されますが、4つになると、何故か最後の 画像ファイルしか描画されません(1~3番目に選択した画像ファイルは描画されない)。 選択した画像ファイルをすべて表示するにはどうしたらいいのか教えてください。 宜しくお願いします。 コードは次のとおりです。 document.getElementById('fileInput').onchange = function() { var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext("2d"); var drwX = 0, drwY = 0;//描画初期位置 var files = this.files; // 選択されたファイルを取得 for (var i = 0; i < files.length; ++i) { var file = this.files[i]; // 画像ファイル以外は処理中止 if (!file.type.match(/^image\/(png|jpeg|gif)$/)) continue; var image = new Image(); var reader = new FileReader(); reader.onload = function(evt) { image.onload = function() { ctx.drawImage(image, drwX, drwY, 50, 50); }; drwX += 50;//次の画像の描画位置を右へ50px drwY += 50;//              下へ50px // 画像のソースに、ファイルのURLを設定 image.src = evt.target.result; } // 読み込んだデータをBase64でエンコードしURLへ reader.readAsDataURL(file); } }

  • javascriptで困っています。教えてください

    canvasタグの画像の描画で困っています。 Imageオブジェクトを生成して、画像ファイルを先読みしておいて var aaa = new Image(); aaa.src = "img/item00.png"; var bbb = new Image(); bbb.src = "img/item01.png"; 配列に入れる var i = [aaa,bbb] 描画コンテキストの取得s取得して、画像を表示させる var canvas = document.getElementById('sample'); if (canvas.getContext) { var context = canvas.getContext('2d'); 座標(10, 10)(50, 50)の位置にイメージを表示 context.drawImage(aaa, 10, 10); context.drawImage(bbb, 50, 50); } としています。このあとクリックなどのきっかけで、画像の絵を入れ替えたいと思い、 var cha1 = i[0].src; var cha2 = i[1].src; i[0].src = cha2; i[1].src = cha1; もう一度描画させているのですが、うまくいきません。 cha1,cha2が取得できているかチェックすると、undifineとでます。 これでは、入れ替えることがでないのでしょうか? 入れ替えるとしたらどのような方法があるのでしょうか。 よろしくお願いします。

  • HTML5のcanvasで描画がされない

    HTML5のcanvas要素を使って描画をしようとしたのですが、図形が表示されません。 コードは以下の通りです。 ・index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>canvasで図形を描く</title> <script type="text/javascript" src="paint.js"></script> </head> <body onLoad="draw()"> <canvas id="mycanvas"width="800" height"800"> </canvas> </body> </html> ・paint.js function draw() { //描画コンテキストの取得 var canvas = document.getElementById('mycanvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.arc(180,150,20,Math.PI*1,Math.PI*2,true); } } このコードでは(180,150)の位置に半径20の円が描画されるはずなのですが、何も表示されませんでした。 どこかコードに誤りがあるのでしょうか? よろしくお願いします。

  • javascriptのcanvasについて

    先日こちらで質問させて頂き、頂いた回答をもとに javascriptのcanvasについて勉強を続けていて、 canvasを2つ重ねたカラーシミュレーションのようなものを作りたいと考えています。 先日教えて頂いた内容をもとに 下記のような記述で2枚目のcanvasの画像を入れ替えることや、 色を変更することは出来ました。 ただ、「進む」ボタンや「戻る」ボタンを押したときに 色がもとの色に戻ってしまうので、色は固定されたまま(この記述でいうと茶色や赤)で 画像を入れ替える方法がわからずにいます。 なにか良い方法はないでしょうか。 <style type="text/css"> .canvas001 { position: absolute; top:100px; left:0px; } .canvas002{ position: absolute; top:100px; left:0px; } </style> <script> onload = function() { image1(); image2(); image3();}; function image1() { var cnvs = document.getElementById('canvas1'); var ctx = cnvs.getContext('2d'); var img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0); }; img.src = "face.png"; }; function image2() { var cnvs = document.getElementById('canvas2'); var ctx = cnvs.getContext('2d'); var img = new Image(); img.onload = function() { ctx.drawImage(img, 0, 0); }; img.src = "hair1.png"; }; var src = [  'hair1.png',  'hair2.png',  'hair3.png' ]; var currentIndex = 0; var currentImage; function hair(){ var img = currentImage = new Image(); img.onload = function() { if(currentImage === img){ var cnvs = document.getElementById('canvas2'); var ctx = cnvs.getContext('2d'); ctx.clearRect(0, 0, cnvs.offsetWidth, cnvs.offsetHeight); ctx.drawImage(img, 0, 0); } }; img.src = src[currentIndex]; } window.back = function(){ currentIndex = (currentIndex - 1 + src.length) % src.length; hair(); } window.foward = function(){ currentIndex = (currentIndex + 1) % src.length; hair(); } function black(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 35; idata[ i*4 + 1 ] = 24; idata[ i*4 + 2 ] = 21; } ctx.putImageData(imagedata,0,0); } function brown(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 140; idata[ i*4 + 1 ] = 96; idata[ i*4 + 2 ] = 37; } ctx.putImageData(imagedata,0,0); } function red(){ var ctx = document.getElementById("canvas2").getContext("2d"); var imagedata = ctx.getImageData(0,0,300,300); var idata = imagedata.data; var num = idata.length; var pix = num / 4; for ( var i = 0 ; i < pix ; i++ ){ var r = idata[ i*4 ]; var g = idata[ i*4 + 1 ]; var b = idata[ i*4 + 2 ]; idata[ i*4 ] = 182 ; idata[ i*4 + 1 ] = 0; idata[ i*4 + 2 ] = 5; } ctx.putImageData(imagedata,0,0); } </script> <body> <div> <div class="canvas001"><canvas id="canvas1" height="300"></canvas></div> <div class="canvas002"><canvas id="canvas2" height="300"></canvas></div> </div> <div> <form><div> <INPUT TYPE=button NAME="submit" VALUE="戻る" onClick="back()"> <INPUT TYPE=button NAME="submit" VALUE="進む" onClick="foward()"> </div></form> </div> <img src="btn_black.png" onclick="black()" > <img src="btn_brown.png" onclick="brown()" > <img src="btn_red.png" onclick="red()" > </body>

  • HTML5での画像表示について

    HTML5を勉強しはじめたばかりの者です。 http://nigohiroki.hatenablog.com/entry/2013/01/04/025502 ここのサイトみながらラインと四角を表示することはできたのですが、 画像を表示することができません。 <!DOCTYPE HTML> <html lang="ja-JP"> <head> <meta charset="UTF-8"> <title>canvasApp</title> </head> <body onload="init()"> <canvas id="first" width="200" height="200"></canvas> <script type="text/javascript"> var canvas = document.getElementById('first'); var ctx = canvas.getContext('2d'); function init(){ var img = new Image(); img.src = "01.jpg"; ctx.drawImage(img, 100, 100, 200, 200); } </script> </body> </html> どこがおかしいのかさっぱりわかりません。 試しに</body>の前に<img src="01.jpg">と入れるとなぜか表示できるのですが、 外すと表示できなくなります。 よろしくお願いします。

    • ベストアンサー
    • HTML
  • C# DrawImage 物理サイズでなく、ピクセルサイズでの描画

    C# で、 Image img = new Bitmap(fileName); Point p = this.PointToClient( new Point( e.X, e.Y ) ); で画像と描画位置を決め、 e.Graphics.DrawImage(img, p); で、そこに画像を描画するのですが、写真によって、同じ1024*768ピクセルなのに、表示される大きさがばらばらです。 Graphics.DrawImage メソッド (Image, Point)の説明を読むと、「指定した位置に、指定した Image を元の物理サイズで描画します」とあり、「元の物理サイズで描画」に問題があることがわかりました。 質問ですが、「指定した位置に、指定した Image をピクセルサイズで描画」するメソッドは何でしょう?探し方が悪いのか、見つけられません。

  • IEの「explorercanvas」で作ったCANVASがスクロール

    IEの「explorercanvas」で作ったCANVASがスクロール出来ない HTML5の<canvas>要素を、擬似的に使えるようにした「explorercanvas」↓ http://code.google.com/p/explorercanvas/ ですが、これを使って<canvas>要素を<div>要素の中に配置したんですが、 親の<div>ボックスをスクロールしても、canvasがスクロールされません。 本物の<canvas>要素はちゃんと出来ます。(FirefoxとChromeで確認) 何か代替策ないでしょうか?(canvas内に再描画しろってか..) (実験したコード) <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Canvas Test</title> <style type="text/css"> </style> <!--[if IE]><script src="/jslib/excanvas.js"></script><![endif]--> </head> <body> <p>CANVAS</p> <h2 style="text-align:center">Canvas TEST By HTML5 or IE(excanvas.js)</h2> <div id="hoge" style="width;500px;overflow:scroll;border:solid 1px gray"></div> <p>イメージ</p> <div id="fuga" style="width;500px;overflow:scroll;border:solid 1px gray"></div> <script type="text/javascript"> //CANVASの場合  var container1 = document.getElementById("hoge");  var canvas = document.createElement("canvas");  canvas.width = 2000;  canvas.height = 500;  container1.appendChild(canvas);  if (typeof(G_vmlCanvasManager) != 'undefined')   canvas = G_vmlCanvasManager.initElement(this.canvas);  var ctx = canvas.getContext('2d');  var img = new Image();  img.src = "/image/mio.jpg" + "?" + new Date().getTime();   img.onload = function() {    ctx.drawImage(img,0,0,2000,500);   }  container1.scrollLeft = 500; //imgの場合  var container2 = document.getElementById("fuga");  var img2 = new Image();  img2.src = "/image/yui.jpg" + "?" + new Date().getTime();  img2.style.width="2000px";  img2.style.height="500px";  container2.appendChild(img2);  container2.scrollLeft = 500; </script> </body> </html>

  • JavaScriptでのフレーム間の値の受け渡し

    はじめまして。 JavaScriptでのフレーム間の値の受け渡しについて、お聞きしたいと思っています。 ・下記left.htmでは、リストボックスから画像名を選択します。 <script type="text/javascript"> <!-- function sample(image1){ parent.fuseaction = image1; location.href="right.htm"; var image1 image1 = image1.jpg image2 = image2.jpg } // --> </script> <body> 下記の画像を選択してください。 <p><select> <option value="0"></option> <option value="image1" selected>画像1</option> <option value="image2">画像2</option> </select></p> </p> <p><input type="button" value="ボタン" name="B3" onClick="sample(image1);"> </p> <p><a href="main.htm" target="main">sample</a> </p> <p>  </p> </body> </html> ・下記right.htmでは、画像名を表示します。 <script type="text/javascript"> <!-- function sample(image1){ } src="sample(image1)" まだ、初心者のため、みなさまに教えて頂きたいと思います。 よろしくお願いします。

  • canvas上で画像を移動する方法について

    javascript超初心者です。 canvas上でimage1.pngをドラッグして移動させるために、次のようなコードを書きました。 window.addEventListener("load", function() { var canvas = document.getElementById("dCanvas"); var ctx=canvas.getContext("2d"); var image = new Image(); image.src="./images/image1.png"; var imageDrag = false; var imageObject = { x:0, y:0, width:100, height:50, }; image.onload = function () { ctx.drawImage(image,imageObject.x, imageObject.y); } canvas.addEventListener("mousemove", function(e){ //マウスの移動 var x = e.clientX; var y = e.clientY; if (imageDrag) { ctx.clearRect(0,0,800,400); ctx.drawImage(image, imageObject.x + x - startX, imageObject.y + y - startY); } }); canvas.addEventListener("mouseup",function(e){ if(imageDrag){ //ドラッグを終えたときのマウスの座標 var x = e.clientX; var y = e.clientY; imageObject.x += x-startX; imageObject.y += y-startY; imageDrag = false; } }); canvas.addEventListener("mousedown",function(e){ var x = e.clientX; var y = e.clientY; if(x > imageObject.x && x < imageObject.x+imageObject.width && y > imageObject.y && y < imageObject.y+imageObject.height){ imageDrag = true; //ドラッグを始めたときのマウスの座標 startX = x; startY = y; } }); canvas.addEventListener("mouseleave",function(){ imageDrag = false; }); var startX = -1; var startY = -1; }, true); パソコンでは作動したのですが、タブレット(Galaxy tab)上の Firefoxではタッチ動作で動きません。 パソコン、タブレット両対応にするには、どうすればよいでしょうか。 よろしくご教授下さい。

専門家に質問してみよう