質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

4246閲覧

スマホ対応のお絵描きツールでタッチしても描けない

nosonosolife

総合スコア42

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2016/06/17 10:10

編集2016/06/17 10:27

javascriptのcanvasでスマホ対応のお絵描きツールを作成したのですが、
pc上では描けるのですが、スマホ上では何も絵画されません。
タッチした座標も取得する様にしたのですが...
原因は一体何なんでしょうか。ご教授よろしくお願いいたします。

javascript

1function drawScript(){ 2 var canvas = document.getElementById('drawCanvas'); 3 canvas.width = 500; 4 canvas.height = 400; 5 var ctx = canvas.getContext('2d'); 6 ctx.beginPath(); 7 ctx.fillStyle = "#fff"; 8 ctx.fillRect(0, 0, 500, 400); 9 $('#undo, #redo').attr('disabled', true); 10 var outputData = new Array(); 11 var outputLength = -1; 12 var isDrawing; 13 var bgColor = "#fff"; 14 var penSize = 3; 15 var penColor = "#000000"; 16 var mouseX; 17 var mouseY; 18 if (window.TouchEvent) { 19 $('canvas').on('touchstart', function(e) { 20 onClick(e); 21 isDrawing = true; 22 }).on('touchmove', function(e) { 23 onMove(e); 24 e.preventDefault(); 25 }).on('touchend', function() { 26 if (!isDrawing) return; 27 saveImageData(); 28 isDrawing = false; 29 }).on('touchcancel', function() { 30 if (!isDrawing) return; 31 saveImageData(); 32 isDrawing = false; 33 }); 34 } else { 35 $('canvas').on('mousedown', function(e) { 36 onClick(e); 37 isDrawing = true; 38 }).on('mousemove', function(e) { 39 onMove(e); 40 }).on('mouseup', function() { 41 if (!isDrawing) return; 42 drawEnd(); 43 saveImageData(); 44 isDrawing = false; 45 }).on('mouseleave', function() { 46 if (!isDrawing) return; 47 drawEnd(); 48 saveImageData(); 49 isDrawing = false; 50 }); 51 } 52 53 function onMove(e) { 54 if (e.buttons === 1 || e.witch === 1) { 55 var rect = e.target.getBoundingClientRect(); 56 if (window.TouchEvent) { 57 var X = (e.changedTouches[0].pageX - rect.left); 58 var Y = (e.changedTouches[0].pageY - rect.top); 59 } else { 60 var X = (e.clientX - rect.left); 61 var Y = (e.clientY - rect.top); 62 } 63 draw(X, Y); 64 }; 65 }; 66 67 function onClick(e) { 68 if (e.button === 0) { 69 var rect = e.target.getBoundingClientRect(); 70 if (window.TouchEvent) { 71 var X = (e.changedTouches[0].pageX - rect.left); 72 var Y = (e.changedTouches[0].pageY - rect.top); 73 } else { 74 var X = (e.clientX - rect.left); 75 var Y = (e.clientY - rect.top); 76 } 77 draw(X, Y); 78 } 79 }; 80 81 function draw(X, Y) { 82 ctx.beginPath(); 83 if (mouseX === "") { 84 ctx.moveTo(X, Y); 85 } else { 86 ctx.moveTo(mouseX, mouseY); 87 } 88 ctx.lineTo(X, Y); 89 ctx.lineCap = "round"; 90 ctx.lineWidth = penSize; 91 ctx.strokeStyle = penColor; 92 ctx.stroke(); 93 mouseX = X; 94 mouseY = Y; 95 }; 96 97 function drawEnd() { 98 mouseX = ""; 99 mouseY = ""; 100 ctx.closePath(); 101 } 102 103 function saveImageData() { 104 // 現在の状態を保存 105 if (outputLength >= outputData.length) { 106 outputData.shift(); 107 } else { 108 ++outputLength; 109 } 110 if (outputLength <= outputData.length) { 111 $('#redo').attr('disabled', true); 112 } 113 outputData[outputLength] = ctx.getImageData(0, 0, canvas.width, canvas.height); 114 $('#undo').attr('disabled', false); 115 } 116}

html

1<script type="text/javascript"> 2<!-- // 3$(function(){ 4 drawScript(); 5}); 6// --> 7</script> 8<canvas id="drawCanvas" width="500" height="400"></canvas>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masaya_ohashi

2016/06/17 10:21

HTMLの方も載せることは可能ですか?
masaya_ohashi

2016/06/17 10:22

あと、Javascriptはこれで全部ですか?drawScriptはどこから呼ばれていますか?
kei344

2016/06/17 17:29

まだ質問が「受付中」になっていますが、いったん「解決済」にされてはいかがでしょうか。
guest

回答1

0

ベストアンサー

Javascript

1if (e.buttons === 1 || e.witch === 1) {

Javascript

1if (e.button === 0)

TouchEventにbuttons,witch,buttonというパラメータはありません。おそらくここでエラーが起きて処理が止まっています。
window.TouchEventで判断したあとにこれらの判断を持って行きましょう。

追記

Chromeのデバイスシミュレータでテストした結果、eはjQuery.Eventでラップされており、originalEventというプロパティに本来のイベントが格納されているようです。クリックのイベントは例外的にjQuery.Eventにもプロパティがコピーされているため、普通にアクセスできるようです。
そして、実際に飛んできたイベントがTouchEventかどうかを調べる判断方法に変えてみました。
さらに、var XやYの宣言タイミングがおかしかったので改善してみました。

Javascript

1function onMove(e) { 2 var rect = e.target.getBoundingClientRect(); 3 var X = undefined; 4 var Y = undefined; 5 if (window.TouchEvent && e.originalEvent instanceof TouchEvent) { 6 X = (e.originalEvent.changedTouches[0].pageX - rect.left); 7 Y = (e.originalEvent.changedTouches[0].pageY - rect.top); 8 } else { 9 if (e.buttons === 1 || e.witch === 1) { 10 X = (e.clientX - rect.left); 11 Y = (e.clientY - rect.top); 12 } 13 } 14 if (X != undefined && Y != undefined) { 15 draw(X, Y); 16 } 17}; 18 19function onClick(e) { 20 var rect = e.target.getBoundingClientRect(); 21 var X = undefined; 22 var Y = undefined; 23 if (window.TouchEvent && e.originalEvent instanceof TouchEvent) { 24 X = (e.originalEvent.changedTouches[0].pageX - rect.left); 25 Y = (e.originalEvent.changedTouches[0].pageY - rect.top); 26 } else { 27 if (e.button === 0) { 28 X = (e.clientX - rect.left); 29 Y = (e.clientY - rect.top); 30 } 31 } 32 if (X != undefined && Y != undefined) { 33 draw(X, Y); 34 } 35};

###補足
PCのChromeではif(window.TouchEvent)はtrueになりますが、マウスでクリックするとMouseEventが飛んできます。なので、いまのイベントハンドラの登録では動作しません(実際私のPC環境では動きませんでした)。
いっそのことイベントハンドラの登録は、どちらもしてしまうべきかと思います。

Javascript

1$('canvas').on('touchstart', function(e) { 2 onClick(e); 3 isDrawing = true; 4}).on('touchmove', function(e) { 5 onMove(e); 6 e.preventDefault(); 7}).on('touchend', function() { 8 if (!isDrawing) return; 9 saveImageData(); 10 isDrawing = false; 11}).on('touchcancel', function() { 12 if (!isDrawing) return; 13 saveImageData(); 14 isDrawing = false; 15}).on('mousedown', function(e) { 16 onClick(e); 17 isDrawing = true; 18}).on('mousemove', function(e) { 19 onMove(e); 20}).on('mouseup', function() { 21 if (!isDrawing) return; 22 drawEnd(); 23 saveImageData(); 24 isDrawing = false; 25}).on('mouseleave', function() { 26 if (!isDrawing) return; 27 drawEnd(); 28 saveImageData(); 29 isDrawing = false; 30}); 31

投稿2016/06/17 10:34

編集2016/06/17 11:28
masaya_ohashi

総合スコア9206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nosonosolife

2016/06/17 10:56

ご回答ありがとうございます。 回答を参考にして書き換えたのですが、それでもスマホのほうでは動きません。 書き換えた後のコード function onMove(e) { var rect = e.target.getBoundingClientRect(); if (window.TouchEvent) { var X = (e.changedTouches[0].pageX - rect.left); var Y = (e.changedTouches[0].pageY - rect.top); } else { if (e.buttons === 1 || e.witch === 1) { var X = (e.clientX - rect.left); var Y = (e.clientY - rect.top); } } draw(X, Y); }; function onClick(e) { var rect = e.target.getBoundingClientRect(); if (window.TouchEvent) { var X = (e.changedTouches[0].pageX - rect.left); var Y = (e.changedTouches[0].pageY - rect.top); } else { if (e.button === 0) { var X = (e.clientX - rect.left); var Y = (e.clientY - rect.top); } } draw(X, Y); };
nosonosolife

2016/06/17 11:43

追記と補足を参考に書き換えて、ようやくスマホでも描くことができたのですが、 タッチした場所よりも大きくずれて絵画されます。 原因は何でしょうか。
masaya_ohashi

2016/06/17 11:55

canvasをcssで拡大したりしていませんか?
nosonosolife

2016/06/17 12:03

拡大はしていませんが、スマホでページが画面の幅いっぱいに表示されるように <meta name="viewport" content="width=640, minimum-scale=0.1"> を設定しています。
nosonosolife

2016/06/17 12:12

あと、canvasはページが表示されたときには非表示の状態で、 ページ内のボタンを押すと、slideToggle(); を実行し表示されるようになっています。
nosonosolife

2016/06/17 12:17

canvasのcssはこちらです canvas#drawCanvas { float: left; margin:0px; padding:0px; width: 500px; height:400px; border: 1px solid #cc4400; }
masaya_ohashi

2016/06/17 12:31

TouchEventのpageX,pageYを参照している箇所を、かわりにscreenX,screenYにしてみてください。もしくは、clientX,clientYにしてみてください。
nosonosolife

2016/06/17 12:44

clientX,clientYに変更したところ上手くいったのですが、 canvasに一本の線を描いた後指を離し、別の場所に線を描くと、 2つの線が繋がってしまいます、原因は何でしょうか。 重ね重ね申し訳ございません。
masaya_ohashi

2016/06/17 12:57

touchendイベントの処理の中でdrawEndを呼んでないからではないでしょうか
nosonosolife

2016/06/17 13:06

無事に、正しくスクリプトが動きました。 お忙しいところ、ご教示いただきありがとうございました。
masaya_ohashi

2016/06/17 13:34

解決したなら解決済みにしておくと他の回答者が終わった質問に間違って答えることがなくなるのでチェックお願いします
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問