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

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

ただいまの
回答率

90.03%

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,548

nosonosolife

score 28

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

function drawScript(){
    var canvas = document.getElementById('drawCanvas');
    canvas.width = 500;
    canvas.height = 400;
    var ctx = canvas.getContext('2d');
    ctx.beginPath();
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, 500, 400);
    $('#undo, #redo').attr('disabled', true);
    var outputData = new Array();
    var outputLength = -1;
    var isDrawing;
    var bgColor = "#fff";
    var penSize = 3;
    var penColor = "#000000";
    var mouseX;
    var mouseY;
    if (window.TouchEvent) {
        $('canvas').on('touchstart', function(e) {
            onClick(e);
            isDrawing = true;
        }).on('touchmove', function(e) {
            onMove(e);
            e.preventDefault();
        }).on('touchend', function() {
            if (!isDrawing) return;
            saveImageData();
            isDrawing = false;
        }).on('touchcancel', function() {
            if (!isDrawing) return;
            saveImageData();
            isDrawing = false;
        });
    } else {
        $('canvas').on('mousedown', function(e) {
            onClick(e);
            isDrawing = true;
        }).on('mousemove', function(e) {
            onMove(e);
        }).on('mouseup', function() {
            if (!isDrawing) return;
            drawEnd();
            saveImageData();
            isDrawing = false;
        }).on('mouseleave', function() {
            if (!isDrawing) return;
            drawEnd();
            saveImageData();
            isDrawing = false;
        });
    }

    function onMove(e) {
        if (e.buttons === 1 || e.witch === 1) {
            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 {
                var X = (e.clientX - rect.left);
                var Y = (e.clientY - rect.top);
            }
            draw(X, Y);
        };
    };

    function onClick(e) {
        if (e.button === 0) {
            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 {
                var X = (e.clientX - rect.left);
                var Y = (e.clientY - rect.top);
            }
            draw(X, Y);
        }
    };

    function draw(X, Y) {
        ctx.beginPath();
        if (mouseX === "") {
            ctx.moveTo(X, Y);
        } else {
            ctx.moveTo(mouseX, mouseY);
        }
        ctx.lineTo(X, Y);
        ctx.lineCap = "round";
        ctx.lineWidth = penSize;
        ctx.strokeStyle = penColor;
        ctx.stroke();
        mouseX = X;
        mouseY = Y;
    };

    function drawEnd() {
        mouseX = "";
        mouseY = "";
        ctx.closePath();
    }

    function saveImageData() {
        // 現在の状態を保存
        if (outputLength >= outputData.length) {
            outputData.shift();
        } else {
            ++outputLength;
        }
        if (outputLength <= outputData.length) {
            $('#redo').attr('disabled', true);
        }
        outputData[outputLength] = ctx.getImageData(0, 0, canvas.width, canvas.height);
        $('#undo').attr('disabled', false);
    }
}
<script type="text/javascript">
<!-- //
$(function(){
    drawScript();
});
// -->
</script>
<canvas id="drawCanvas" width="500" height="400"></canvas>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • masaya_ohashi

    2016/06/17 19:21

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

    キャンセル

  • masaya_ohashi

    2016/06/17 19:22

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

    キャンセル

  • kei344

    2016/06/18 02:29

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

    キャンセル

回答 1

checkベストアンサー

0

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

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

 追記

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

function onMove(e) {
    var rect = e.target.getBoundingClientRect();
    var X = undefined;
    var Y = undefined;
    if (window.TouchEvent && e.originalEvent instanceof TouchEvent) {
        X = (e.originalEvent.changedTouches[0].pageX - rect.left);
        Y = (e.originalEvent.changedTouches[0].pageY - rect.top);
    } else {
        if (e.buttons === 1 || e.witch === 1) {
            X = (e.clientX - rect.left);
            Y = (e.clientY - rect.top);
        }
    }
    if (X != undefined && Y != undefined) {
        draw(X, Y);
    }
};

function onClick(e) {
    var rect = e.target.getBoundingClientRect();
    var X = undefined;
    var Y = undefined;
    if (window.TouchEvent && e.originalEvent instanceof TouchEvent) {
        X = (e.originalEvent.changedTouches[0].pageX - rect.left);
        Y = (e.originalEvent.changedTouches[0].pageY - rect.top);
    } else {
        if (e.button === 0) {
            X = (e.clientX - rect.left);
            Y = (e.clientY - rect.top);
        }
    }
    if (X != undefined && Y != undefined) {
        draw(X, Y);
    }
};

補足

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

$('canvas').on('touchstart', function(e) {
    onClick(e);
    isDrawing = true;
}).on('touchmove', function(e) {
    onMove(e);
    e.preventDefault();
}).on('touchend', function() {
    if (!isDrawing) return;
    saveImageData();
    isDrawing = false;
}).on('touchcancel', function() {
    if (!isDrawing) return;
    saveImageData();
    isDrawing = false;
}).on('mousedown', function(e) {
    onClick(e);
    isDrawing = true;
}).on('mousemove', function(e) {
    onMove(e);
}).on('mouseup', function() {
    if (!isDrawing) return;
    drawEnd();
    saveImageData();
    isDrawing = false;
}).on('mouseleave', function() {
    if (!isDrawing) return;
    drawEnd();
    saveImageData();
    isDrawing = false;
});

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/17 22:00

    touchcancelも同じようですね

    キャンセル

  • 2016/06/17 22:06

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

    キャンセル

  • 2016/06/17 22:34

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

    キャンセル

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

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる