ざっくりとこういう構造かなぁと
さて,スクリプト全文です.
細かい装飾や表示位置は自分で変更してみてください.
<!DOCTYPE html> <html> <head> <title>camera paint</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"> <!-- metaタグで スマホの挙動を制限している --> <script src="megapix-image.js"></script><!-- 外部の便利なライブラリを読み込んでいる --> </head> <body> <h1>camera</h1> カメラを起動,又は写真を選択<br> <input type="file" accept="image/*" capture="camera" id="mycam" onchange="myCamera(mycam)"/> <br> <canvas id="myCanvas" style="border:1px solid #000000;"></canvas> <script type="text/javascript"> var canvas; var camCanvas; var paintSwitch = false; var oldX = 0; var oldY = 0; var myColor = "rgb(255,0,0)";//色を動的に変えられるようにするために変数宣言しちゃう var myLine = 0; //---スマホのOS取得 var ua = navigator.userAgent;//User Agent(まぁ機種名みたいなの)を取得して変数uaに代入しなさい //--- //以下iPhoneの時の挙動 if (ua.indexOf("iPad") >= 0 || ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){ //特に挙動はまだ決めていない } //以下Androidの時の挙動 if (ua.indexOf("Android") >= 0){ //特に挙動はまだ決めていない } //--------- window.onload = function() {//これ読み込んだ時に,,, syokika();//syokikaを実行してね } function syokika(){//で,これがsyokikaね canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); //--ここからスマホのタッチの挙動<−NEW!! canvas.addEventListener("touchmove",myTouchDraw,false); canvas.addEventListener("touchstart",myTouchStart,false); canvas.addEventListener("touchend",myTouchEnd,false); } //--タッチの挙動ここから function myTouchStart(atai){ paintSwitch = true; oldX = atai.touches[0].pageX - canvas.offsetLeft;//オフセット(ずれ)の修正=よこ oldY = atai.touches[0].pageY - canvas.offsetTop;//オフセット(ずれ)の修正=たて } function myTouchEnd(){ paintSwitch = false; } //--タッチの挙動ここまで //--カメラの画像 function myCamera(mycam){ var myFile = mycam.files[0]; new MegaPixImage(myFile).render(myCanvas, { width : 300}); } //--カメラの画像処理ここまで function myWidth(myWidth){ myLine = myWidth; } function myTouchDraw(atai) { if (!paintSwitch) return; atai.preventDefault();//これすると縦スクロールがなくなる var x = atai.touches[0].pageX - canvas.offsetLeft;//なんかタッチの場合はpageXじゃないとだめ var y = atai.touches[0].pageY - canvas.offsetTop;//なんかタッチの場合はpageYじゃないとだめ var context = canvas.getContext("2d"); context.strokeStyle = myColor;//色は動的に変えられるように変数にすちゃったよね context.lineWidth = myLine;//線の太さ context.beginPath();//線を描き始めます context.moveTo(oldX, oldY);//この点から context.lineTo(x, y);//この点まで context.stroke();//描いてね context.closePath();//線はここまで oldX = x; oldY = y; } function myRed(){ myColor = "rgb(255,0,0)"; } function myGreen(){ myColor = "rgb(0,255,0)"; } function myBlu(){ myColor = "rgb(0,0,255)"; } function myYel(){ myColor = "rgb(255,255,0)"; } function myGray(){ myColor = "rgb(128,128,128)"; } function myBlack(){ myColor = "rgb(0,0,0)"; } //---画像に変換ボタンを押すとここにfunctionが実行される function screenshot(){ var myimage = canvas.toDataURL(); //以下iPhoneの時の挙動 上の方で機種をグローバル変数uaに入れてあるのでifで機種が分かる if (ua.indexOf("iPad") >= 0 || ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){ document.getElementById("newImg").src = myimage;//newImgeというIDを探してPNG入れてね } //以下Androidの時の挙動 上の方で機種をグローバル変数uaに入れてあるのでifで機種が分かる if (ua.indexOf("Android") >= 0){ //androimageというiDがあるimgタグのソース(URL入れるところ)に入れちゃう document.getElementById("androimage").src = myimage; } } //--- </script> <form> <input type="button" value="RED" onclick="myRed()"> <input type="button" value="GREEEN" onclick="myGreen()"> <input type="button" value="BLUE" onclick="myBlu()"> <input type="button" value="YELLOW" onclick="myYel()"> <input type="button" value="GRAY" onClick="myGray()"> <input type="button" value="BLACK" onClick="myBlack()"> </form> </ br> <pre> 線の太さ<input id="myRange" value="1" type="range" max="10" min="1" step="0.1" onChange="myWidth(this.value)" /> </pre> <hr> <form> <input type="button" value="画像に変換" onclick="screenshot()"> <!-- onclickでscreenshotというfunction実行してね --> </form> <div><img id="newImg"></div> <!-- iPhone用です このDIVのIDを探してここに画像を入れる --> </ br> <img src="" id="androimage" border="1"><!-- Androidの時の画像保存用 --> <pre> 画像を長押しして保存 </pre> </body> </html>
次にJavascript内のどこかに次のfunctionを入れます
//--カメラの画像 function myCamera(mycam){ var myFile = mycam.files[0]; new MegaPixImage(myFile).render(myCanvas, { width : 300}); } //--カメラの画像処理ここまで
前項のファイル選択とこのスクリプトを入れると,canvas上に写真が描画されます.
(iPhone5,nexus7確認済み)
それではカメラを起動するスクリプトです.
今回はhtml media captureというものを使います.
<input type="file" accept="image/*" capture="camera" id="mycam" onchange="myCamera(mycam)"/>
少しずつ解説をしていきましょう.
<input type=”file” accept=”image/*” capture=”camera” id=”mycam” onchange=”myCamera(mycam)”/>
これはファイル入力するものですよ〜という意味.この”file”は決まった引数です(変えちゃだめ).線の太さを決めるスライドバーでは”range”を使っていましたね.
<input type=”file” accept=”image/*” capture=”camera” id=”mycam” onchange=”myCamera(mycam)”/>
このあたりは変えないでください.ここを accept=”audio/*” capture=”microphone”にすると録音ができるようです.
<input type=”file” accept=”image/*” capture=”camera” id=”mycam” onchange=”myCamera(mycam)“/>
myCamera( は実行しに行くfunction名です. id=”mycam” と myCamera(の引数であるmycam)は,同じにしておいてください.でないと動かない,,,,
これで「ファイルを選択」のボタンが表示されます.ボタンに表示される文字はOSや機種で若干変わる可能性があります.
これを実行すると,カメラで撮影するか,すでに撮影した写真を読み込むか選択できます.カメラを起動し,撮影してみてください.
iPhoneでは横向き(ランドスケープモード)で撮影した方が良いようです.
HTML5についてはこのカメラにお絵かきで一旦終了します.
ここでは,まずカメラを起動して画像をcanvasに読み込みます.
そのために,ライブラリを使用します.ライブラリは便利機能を別のファイルに記述しておいて呼び出すというものです.代表的なものにjQueryがあります.
今回は,画像処理関係でiphoneに起きるトラブルを解消してくれるライブラリです.
ここをクリックし,開いたファイルをそのままの名前(megapix-image.js)で保存してください.(Macのみ)
Windowsの場合は,どうすればいいのか分かりませんが,改行されないで保存できるようにいろいろやってみてください.
たぶん開いてテキストエディタにコピペして,指定の名前で保存かと.
これを,いまから作成するHTMLファイルと同じ階層に配置します.
ここまでが準備です.
タッチお絵かきもまもなく終了です.
まずは現在のプログラムに以下のパーツを追加して,いろいろな色で塗れるようにしてみましょう.AとBの両方を追加してください.どこに入れるかは,考えてみましょう.
(1)変数設定を増やす
var myColor = "rgb(255,0,0)"; var myLine = 0;
(2)このfunctionをどこかに
function myWidth(myWidth){ myLine = myWidth; }
(3)このfunction達をどこかに
function myRed(){ myColor = "rgb(255,0,0)"; } function myGreen(){ myColor = "rgb(0,255,0)"; } function myBlu(){ myColor = "rgb(0,0,255)"; } function myYel(){ myColor = "rgb(255,255,0)"; } function myGray(){ myColor = "rgb(128,128,128)"; } function myBlack(){ myColor = "rgb(0,0,0)"; }
(4)context.strokeStyleをコメントアウトし(頭に// つけて無効にする)代わりに下記2行目のを追加.これで変数myColorの色に変更できる(PC用とスマホ用では処理しているfunctionが違うのに注意 つまりfunction draw()のところだけでなく,スマホ用の部分も変更しよう)
//context.strokeStyle = "rgba(255,0,0,1)"; context.strokeStyle = myColor
(5)
context.lineWidthをコメントアウトし下記の2行目を追加
(PC用とスマホ用では処理しているfunctionが違うのに注意)
//context.lineWidth = 1;//線の太さ context.lineWidth = myLine;
<form> <input type="button" value="RED" onclick="myRed()"> <input type="button" value="GREEEN" onclick="myGreen()"> <input type="button" value="BLUE" onclick="myBlu()"> <input type="button" value="YELLOW" onclick="myYel()"> <input type="button" value="GRAY" onClick="myGray()"> <input type="button" value="BLACK" onClick="myBlack()"> </form> </ br> <pre> 線の太さ<input id="myRange" value="1" type="range" max="10" min="1" step="0.1" onChange="myWidth(this.value)" /> </pre> <hr>
これでうまくいけばiPhoneでもAndroidでもどちらでも使えるスマホ用(PCも動くと思います)お絵かきツールができます
iPhoneとAndroid(nexus7)で動作確認しました.
<!DOCTYPE html> <html> <head> <title>touch paint</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"> <!-- metaタグで スマホの挙動を制限している --> </head> <body> <h1>Key2</h1> <canvas id="myCanvas" width="300" height="300" style="border:1px solid #000000;"></canvas> <script type="text/javascript"> var canvas; var paintSwitch = false; var oldX = 0; var oldY = 0; //---スマホのOS取得 var ua = navigator.userAgent;//User Agent(まぁ機種名みたいなの)を取得して変数uaに代入しなさい //--- //以下iPhoneの時の挙動 if (ua.indexOf("iPad") >= 0 || ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){ //特に挙動はまだ決めていない } //以下Androidの時の挙動 if (ua.indexOf("Android") >= 0){ //特に挙動はまだ決めていない } //--------- window.onload = function() {//これ読み込んだ時に,,, syokika();//syokikaを実行してね }; function syokika(){//で,これがsyokikaね canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); //--ここからPCのマウス入力の挙動(タッチが動作しているか確認のため以下3行コメントアウトしてますがPCで動作させる場合はコメントアウトを外してください //canvas.addEventListener("mousemove", draw, true); //canvas.addEventListener("mousedown", myMove, false); //canvas.addEventListener("mouseup", myMouseUp, false); //--ここからスマホのタッチの挙動<−NEW!! canvas.addEventListener("touchmove",myTouchDraw,false); canvas.addEventListener("touchstart",myTouchStart,false); canvas.addEventListener("touchend",myTouchEnd,false); } //--PCのマウス入力時の挙動 function myMove(atai){ paintSwitch = true; oldX = atai.clientX - canvas.offsetLeft;//オフセット(ずれ)の修正=よこ oldY = atai.clientY - canvas.offsetTop;//オフセット(ずれ)の修正=たて } function myMouseUp(){ paintSwitch = false; } //--PCの挙動ここまで //--タッチの挙動ここから function myTouchStart(atai){ paintSwitch = true; oldX = atai.touches[0].pageX - canvas.offsetLeft;//オフセット(ずれ)の修正=よこ oldY = atai.touches[0].pageY - canvas.offsetTop;//オフセット(ずれ)の修正=たて } function myTouchEnd(){ paintSwitch = false; } //--タッチの挙動ここまで //setInterval(draw, 10);//10msec起きに描いてね function draw(atai) { if (!paintSwitch) return; var x = atai.clientX - canvas.offsetLeft; var y = atai.clientY - canvas.offsetTop; //var can = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); context.strokeStyle = "rgba(255,0,0,1)"; context.lineWidth = 1; context.beginPath(); context.moveTo(oldX, oldY); context.lineTo(x, y); context.stroke(); context.closePath(); oldX = x; oldY = y; } function myTouchDraw(atai) { if (!paintSwitch) return; atai.preventDefault();//これすると縦スクロールがなくなる var x = atai.touches[0].pageX - canvas.offsetLeft;//なんかタッチの場合はpageXじゃないとだめ var y = atai.touches[0].pageY - canvas.offsetTop;//なんかタッチの場合はpageYじゃないとだめ //var can = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); context.strokeStyle = "rgba(255,0,0,1)";//16進数でなくこういう描き方もあります aはアルファ=透明チャンネル //context.strokeStyle = "rgb(255,0,0)";//アルファでなくてもOK context.lineWidth = 1;//線の太さ context.beginPath();//線を描き始めます context.moveTo(oldX, oldY);//この点から context.lineTo(x, y);//この点まで context.stroke();//描いてね context.closePath();//線はここまで oldX = x; oldY = y; } //---画像に変換ボタンを押すとここにfunctionが実行される function screenshot(){ var myimage = canvas.toDataURL(); //以下iPhoneの時の挙動 上の方で機種をグローバル変数uaに入れてあるのでifで機種が分かる if (ua.indexOf("iPad") >= 0 || ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){ document.getElementById("newImg").src = myimage;//newImgeというIDを探してPNG入れてね } //以下Androidの時の挙動 上の方で機種をグローバル変数uaに入れてあるのでifで機種が分かる if (ua.indexOf("Android") >= 0){ //androimageというiDがあるimgタグのソース(URL入れるところ)に入れちゃう document.getElementById("androimage").src = myimage; } } //--- </script> <form> <input type="button" value="画像に変換" onclick="screenshot()"> <!-- onclickでscreenshotというfunction実行してね --> </form> <div><img id="newImg"></div> </ br> <!-- このDIVのIDを探してここに画像を入れる --> <img src="" id="androimage" width="300" height="300"> </body> </html>
102行目に縦スクロールロックを入れてあります
120〜138行目は「画像に変換」ボタンを押したときに実行されます.ifを使ってAndroidとiPhoneの時の挙動を分けています.
それではソースです.
例によって完璧にはなっていません
<!DOCTYPE html> <html> <head> <title>touch paint</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"> <!-- metaタグで スマホの挙動を制限している --> </head> <body> <h1>Key2</h1> <canvas id="myCanvas" width="300" height="300" style="border:1px solid #000000;"></canvas> <script type="text/javascript"> var canvas; var paintSwitch = false; var oldX = 0; var oldY = 0; //---スマホのOS取得 var ua = navigator.userAgent;//User Agent(まぁ機種名みたいなの)を取得して変数uaに代入しなさい //--- //以下iPhoneの時の挙動 if (ua.indexOf("iPad") >= 0 || ua.indexOf("iPhone") >= 0 || ua.indexOf("iPod") >= 0){ //特に挙動はまだ決めていない } //以下Androidの時の挙動 if (ua.indexOf("Android") >= 0){ //特に挙動はまだ決めていない } //--------- window.onload = function() {//これ読み込んだ時に,,, syokika();//syokikaを実行してね }; function syokika(){//で,これがsyokikaね canvas = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); //--ここからPCのマウス入力の挙動 //canvas.addEventListener("mousemove", draw, true); //canvas.addEventListener("mousedown", myMove, false); //canvas.addEventListener("mouseup", myMouseUp, false); //--ここからスマホのタッチの挙動<−NEW!! canvas.addEventListener("touchmove",myTouchDraw,false); canvas.addEventListener("touchstart",myTouchStart,false); canvas.addEventListener("touchend",myTouchEnd,false); } //--PCのマウス入力時の挙動 function myMove(atai){ paintSwitch = true; oldX = atai.clientX - canvas.offsetLeft;//オフセット(ずれ)の修正=よこ oldY = atai.clientY - canvas.offsetTop;//オフセット(ずれ)の修正=たて } function myMouseUp(){ paintSwitch = false; } //--PCの挙動ここまで //--タッチの挙動ここから function myTouchStart(atai){ paintSwitch = true; oldX = atai.touches[0].pageX - canvas.offsetLeft;//オフセット(ずれ)の修正=よこ oldY = atai.touches[0].pageY - canvas.offsetTop;//オフセット(ずれ)の修正=たて } function myTouchEnd(){ paintSwitch = false; } //--タッチの挙動ここまで //setInterval(draw, 10);//10msec起きに描いてね function draw(atai) { if (!paintSwitch) return; var x = atai.clientX - canvas.offsetLeft; var y = atai.clientY - canvas.offsetTop; //var can = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); context.strokeStyle = "rgba(255,0,0,1)"; context.lineWidth = 1; context.beginPath(); context.moveTo(oldX, oldY); context.lineTo(x, y); context.stroke(); context.closePath(); oldX = x; oldY = y; } function myTouchDraw(atai) { if (!paintSwitch) return; var x = atai.touches[0].pageX - canvas.offsetLeft;//なんかタッチの場合はpageXじゃないとだめ var y = atai.touches[0].pageY - canvas.offsetTop;//なんかタッチの場合はpageYじゃないとだめ //var can = document.getElementById("myCanvas"); var context = canvas.getContext("2d"); context.strokeStyle = "rgba(255,0,0,1)";//16進数でなくこういう描き方もあります aはアルファ=透明チャンネル //context.strokeStyle = "rgb(255,0,0)";//アルファでなくてもOK context.lineWidth = 1;//線の太さ context.beginPath();//線を描き始めます context.moveTo(oldX, oldY);//この点から context.lineTo(x, y);//この点まで context.stroke();//描いてね context.closePath();//線はここまで oldX = x; oldY = y; } //---ファイルに書き出す用 function screenshot(){ var png = canvas.toDataURL(); document.getElementById("newImg").src = png;//newImgeというIDを探してPNG入れてね } //--- </script> <form> <input type="button" value="画像に変換" onclick="screenshot()"> <!-- onclickでscreenshotというfunction実行してね --> </form> <div><img id="newImg"></div> <!-- このDIVのIDを探してここに画像を入れる --> </body> </html>
102行目の oldX = atai.touches[0].clientX – canvas.offsetLeft;
touche[0]は1本指でタッチという意味です.
ただ,このままでは線を描いた時にスクロールしてうまく行きません.
そこで,
atai.preventDefault();
を101と102行目の間に入れます.
スマートホンでタッチした座標を取り出す仕組みを組み込んでみましょう
構文は
canvas.addEventListener(“touchstart”,myTouchStart,false);
です.
このcanvasはすでに
canvas = document.getElementById(“myCanvas”);
で指定していますね.
canvas.addEventListener(“touchstart”,myTouchStart,false);
平たくいうと「反応検出器(EventListner)を追加(add)して,そのうち”touchstart”という反応が出たら」という意味でしょうか.
canvas.addEventListener(“touchstart”,myTouchStart,false);
myTouchStarというfuctionを実行してね.
で最後のfalseはこういうものだと思ってください.どの説明みてもよく分かりません,,,気になる方はキャプチャリングフェーズとか補足フェーズで検索してみてください.
PC版での入力はマウスを使いました.
このマウス入力は
canvas.addEventListener("mousemove", draw, true);//マウスが動いたとき波drawをやりな canvas.addEventListener("mousedown", myMove, false);//マウスが押された時はmyMoveをやりな canvas.addEventListener("mouseup", myMouseUp, false);//マウスが上がったときはmtMouseUpをやっとかめ
で取得しました.
スマートホンでマウスは使えませんから,タッチイベントというものを使います.
canvas.addEventListener("touchmove",myTouchDraw,true); canvas.addEventListener("touchstart",myTouchStart,false); canvas.addEventListener("touchend",myTouchEnd,false);
では,スマートホン用に改造してみましょう〜