千葉 (2011年5月25日 21:00) 流通システム部 / HTML5
<!DOCTYPE html> <html> <head> <meta charset="shift-jis"> </head> <body OnLoad="init()"> <canvas id="canvas" width="661" height="500" style="border:1px solid #CCC;"></canvas> </body> </html>
var timerID; var iCursorX = 0; // カーソルX座標 var iCursorY = 0; // カーソルY座標 var bClickFlg; var iCount; // 画像サイズ var iImageWidth = 3306; var iImageHeight = 2338; // キャンバスサイズ var iCanvasWidth = 661; var iCanvasHeight = 467; // 拡大率 var iZoom; // 拡大後のサイズ var iDrawWidth; var iDrawHeight; // 初期化処理 function init() { iDrawWidth = iCanvasWidth; iDrawHeight = iCanvasHeight; bClickFlg = false; var img = document.createElement('img'); img.src = "./hoge.jpg"; var canvas = document.getElementById('canvas'); if ( ! canvas || ! canvas.getContext ) return false; var context = canvas.getContext('2d'); // クリック時の処理 canvas.onmousedown = mouseDownListner; function mouseDownListner(e) { adjustXY(e); bClickFlg = true; iCount = 1; } canvas.onmouseup = mouseUpListner; function mouseUpListner(e) { adjustXY(e); bClickFlg = false; } setTimer(); } // タイマーの設定 function setTimer(){ clearInterval(timerID); timerID = setInterval("draw()", 50); } // 絶対座標→相対座標に変換 function adjustXY(e) { var rect = e.target.getBoundingClientRect(); iCursorX = e.clientX - rect.left; iCursorY = e.clientY - rect.top; } // 描画処理 function draw(){ var img = document.createElement('img'); img.src = "./hoge.jpg"; var canvas = document.getElementById('canvas'); if ( ! canvas || ! canvas.getContext ) return false; var context = canvas.getContext('2d'); // 表示クリア context.clearRect(0, 0, iCanvasWidth, 500); if(bClickFlg){ iZoom = iCount; iDrawWidth = parseInt(iImageWidth / iZoom); iDrawHeight = parseInt(iImageHeight / iZoom); var sx = parseInt(getDrawX(iCursorX) - iDrawWidth / 2); var sy = parseInt(getDrawY(iCursorY) - iDrawHeight / 2); if(sx + iDrawWidth >= iImageWidth) iDrawWidth = iImageWidth - sx; if(sy + iDrawHeight >= iImageHeight) iDrawHeight = iImageHeight - sy; if(sx < 0) sx = 0; if(sy < 0) sy = 0; context.drawImage(img, sx, sy, iDrawWidth, iDrawHeight, 0, 0, iCanvasWidth, iCanvasHeight); context.fillText("Zoom:" + iZoom, 0, 480); // カウントアップ iCount = iCount + 1; }else{ context.drawImage(img, 0, 0, iImageWidth, iImageHeight, 0, 0, iCanvasWidth, iCanvasHeight); } } function getDrawX(viX){ return iImageWidth / iCanvasWidth * viX; } function getDrawY(viY){ return iImageHeight / iCanvasHeight * viY; }
HTML5 Canvasを使った画像の拡大+アニメーション
千葉 (2011年5月25日 21:00)
流通システム部 / HTML5
突然ですが、こちらの記事に触発され、HTML5 Canvasを少しは触ってみようと思い、
画像の拡大を行うJavaScriptのコードを書いてみました。
ただ拡大するだけではつまらない(その辺にいくらでも転がっている)ので、
マウスがクリックされている間、
クリックされた位置を中心に拡大するアニメーションを追加してみました。
HTMLコード JavaScriptコード
var timerID; var iCursorX = 0; // カーソルX座標 var iCursorY = 0; // カーソルY座標 var bClickFlg; var iCount; // 画像サイズ var iImageWidth = 3306; var iImageHeight = 2338; // キャンバスサイズ var iCanvasWidth = 661; var iCanvasHeight = 467; // 拡大率 var iZoom; // 拡大後のサイズ var iDrawWidth; var iDrawHeight; // 初期化処理 function init() { iDrawWidth = iCanvasWidth; iDrawHeight = iCanvasHeight; bClickFlg = false; var img = document.createElement('img'); img.src = "./hoge.jpg"; var canvas = document.getElementById('canvas'); if ( ! canvas || ! canvas.getContext ) return false; var context = canvas.getContext('2d'); // クリック時の処理 canvas.onmousedown = mouseDownListner; function mouseDownListner(e) { adjustXY(e); bClickFlg = true; iCount = 1; } canvas.onmouseup = mouseUpListner; function mouseUpListner(e) { adjustXY(e); bClickFlg = false; } setTimer(); } // タイマーの設定 function setTimer(){ clearInterval(timerID); timerID = setInterval("draw()", 50); } // 絶対座標→相対座標に変換 function adjustXY(e) { var rect = e.target.getBoundingClientRect(); iCursorX = e.clientX - rect.left; iCursorY = e.clientY - rect.top; } // 描画処理 function draw(){ var img = document.createElement('img'); img.src = "./hoge.jpg"; var canvas = document.getElementById('canvas'); if ( ! canvas || ! canvas.getContext ) return false; var context = canvas.getContext('2d'); // 表示クリア context.clearRect(0, 0, iCanvasWidth, 500); if(bClickFlg){ iZoom = iCount; iDrawWidth = parseInt(iImageWidth / iZoom); iDrawHeight = parseInt(iImageHeight / iZoom); var sx = parseInt(getDrawX(iCursorX) - iDrawWidth / 2); var sy = parseInt(getDrawY(iCursorY) - iDrawHeight / 2); if(sx + iDrawWidth >= iImageWidth) iDrawWidth = iImageWidth - sx; if(sy + iDrawHeight >= iImageHeight) iDrawHeight = iImageHeight - sy; if(sx < 0) sx = 0; if(sy < 0) sy = 0; context.drawImage(img, sx, sy, iDrawWidth, iDrawHeight, 0, 0, iCanvasWidth, iCanvasHeight); context.fillText("Zoom:" + iZoom, 0, 480); // カウントアップ iCount = iCount + 1; }else{ context.drawImage(img, 0, 0, iImageWidth, iImageHeight, 0, 0, iCanvasWidth, iCanvasHeight); } } function getDrawX(viX){ return iImageWidth / iCanvasWidth * viX; } function getDrawY(viY){ return iImageHeight / iCanvasHeight * viY; }以下、コードの簡単な説明です。
36行目~49行目
マウスのボタンが押されているかどうかを、
それぞれCanvasのonmousedown、onmouseupイベントで取得しています。
55~58行目では、タイマーの設定を行っています。
SetIntervalを用い、draw関数を50ミリ秒(0.05秒)毎に呼び出し、
描画を行っています。
68行目~103行目が実際の描画処理です。
マウスが押されていれば、
画像のサイズ、Canvasのサイズ、拡大する倍率より描画する範囲を計算し、
drawImageメソッドを使用して元画像から切り出した範囲を
Canvasに描画しています。
マウスが押されていない場合は、元画像をそのまま表示するようにしています。
拡大する倍率は、99行目にて処理が行われる度にカウントアップを行い、
決定しています。
なお、画面がクリックされたときに保持している座標はキャンバス上での座標なので、
105行目~111行目ので画像のどの位置がクリックされたかを計算して求めています。
動作確認は、Chromeにて行いました。
今回、拡大率に特に制限は設けていないので、
マウスを押し続けている限り、延々と拡大を続けるようになっています。
注意する点として、drawImage関数の第2引数から第5引数で指定する矩形領域は、
描画する画像の範囲内である必要があります。
画像の幅、高さを超えてしまった場合、エラーとなってしまいますので、
89~93行目で、矩形が常に画像内に収まるよう、補正を行っています。