画像を縮小してトリミング
Android端末を買ったので興味が出たのでやってみた。
方針としては、
・フォームで指定したFileReaderで読み込んで画像をCanvasに書き出す。
・Canvasの画像の表示位置をマウスイベントで移動させる。
・スライドバーで画像の縮小率を変える。
・とりあえず、Chromeで動けばいいや。
コードはこんな
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>キャンバスに画像を読み込んでトリミング</title> <script type="text/javascript"> // マウスボタンの状態 var mouseDown = false; // Canvasサイズ var viewSize = 400; // トリミングサイズ var trimSize = 200; var trimPadding = 100; // 画像描画開始位置 var viewX = 0; var viewY = 0; // マウスボタンを押したときの位置 var startX = 0; var startY = 0; // 読み込んだイメージのサイズ var imageWidth; var imageHeight; var canvas; var context; var img; // 縮小率 var range; var retio = 1; // トリム結果の表示先 var trimCanvas; function setUp() { // Canvas canvas = document.getElementById('view_canvas'); canvas.width = viewSize; canvas.height = viewSize; trimCanvas = document.getElementById('trim_canvas'); trimCanvas.width = trimSize; trimCanvas.height = trimSize; // 画像 img = new Image(); img.onload = function() { context = canvas.getContext('2d'); draw(0,0); imageWidth = 0 - img.width; imageHeight = 0 - img.height; } // スライドバー range = document.getElementById('image_ratio'); range.onchange = function() { viewX = 0; viewY = 0; ratio = this.value / 100; draw(0, 0); } } // Canvasに選択した画像を展開 function preview(ele) { // ファイルが選択されているか? if (!ele.files.length) return; // Canvas使えるか? if ( ! canvas || ! canvas.getContext ) return; // 対象型式の画像か? var file = ele.files[0]; if (!/^image\/(png|jpeg|gif)$/.test(file.type)) return; // リーダー var reader = new FileReader(); reader.onload = function() { img.src = reader.result; } //読み込み実施 viewX = 0; viewY = 0; range.value = 100; ratio = 1; reader.readAsDataURL(file); } // 画像の表示位置変更 function onCanvasMouseMove(event) { if (mouseDown){ // 横位置計算 viewX = viewX + (event.clientX - startX) / 20; // 画像の外まで飛んでいかないように if(viewX > trimPadding ) viewX = trimPadding; var maxX = imageWidth * ratio + viewSize - trimPadding; if(viewX < maxX) { viewX = maxX; } // 縦位置計算 viewY = viewY + (event.clientY - startY) / 20; // 画像の外まで飛んでいかないように if(viewY > trimPadding ) viewY = trimPadding; var maxY = imageHeight * ratio + viewSize - trimPadding; if(viewY < maxY) { viewY = maxY; } // 再描画 draw(viewX, viewY); } } // キャンバス上のマウスボタン押下 function onCanvasMouseDown(event) { mouseDown = true; startX = event.clientX; startY = event.clientY; } // キャンバス上のマウスボタン開放 function onCanvasMouseUp() { mouseDown = false; startX = 0; startY = 0; } // 画像をキャンバスに描画 function draw(x, y) { context.fillRect(0,0,viewSize,viewSize); context.drawImage(img, x, y, img.width * ratio, img.height * ratio); context.strokeStyle = 'rgb(0,0,0)'; context.strokeRect(trimPadding - 1, trimPadding - 1, trimSize + 2, trimSize + 2); context.strokeStyle = 'rgb(255,255,255)'; context.strokeRect(trimPadding - 2, trimPadding - 2, trimSize + 4, trimSize + 4); } // トリミング実施 function trimImage() { var trimData = context.getImageData(trimPadding, trimPadding, trimSize, trimSize); var trimContext = trimCanvas.getContext('2d'); trimContext.putImageData(trimData, 0, 0 ); } </script> </head> <body onload="setUp();"> <form> <input type="file" name="file" onchange="preview(this);" /> <hr /> <h4>キャンバスに画像を読み込んでトリミング</h4> <canvas id="view_canvas" onmousemove="onCanvasMouseMove(event);" onmousedown="onCanvasMouseDown(event);" onmouseup="onCanvasMouseUp();" onmouseout="onCanvasMouseUp();" style="border:solid 1px black;"> </canvas> <canvas id="trim_canvas" style="border:solid 1px black;"> </canvas> <br/> 10% <input type="range" id="image_ratio" min="10" max="100" value="100" style="width:350px;"/> 100% <br/> <input type="button" value="切り出し" onclick="trimImage()"/> <hr/> </form> </body> </html>
おお、動いた。
FireFoxだとスライドバーが使えないけど、そこをクリアすればScript自体は動きそう。
OperaとSafariは試してないけど、どうだろ?
IEはまあムリ。ExplorerCanvasはともかくFileReaderが。