2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【入門者向け】Canvas入門講座#16 マウスドラッグで線を引いてみよう【JavaScript】

Last updated at Posted at 2020-12-02

#問題16

マウスダウンで線の描画を開始し
マウスムーブで線を描画し
マウスアップで線の描画を終えるようにしなさい。
canvasの外にカーソルが出た場合も線の描画を終えること。

線の太さは3で色は#000000であること。

以下のHTMLを使用すること。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>問題16</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => {    
    $('#my-canvas').mousedown(e => {        
    });

    $('#my-canvas').mousemove(e => {        
    });

    $('#my-canvas').mouseup(e => {        
    });

    $('#my-canvas').mouseout(e => {        
    });
});
</script>
</head>
<body>
<canvas id="my-canvas" width="500" height="300"></canvas>
</body>
</html>

#解答

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>問題16</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script>
$(() => {

    let preX = 0, // 1つ前のX座標
        preY = 0, // 1つ前のY座標
        drawFlag = false;   // 線を描画中か

    $('#my-canvas').mousedown(e => {
        // canvasの左上隅を原点とする座標を求める
        const downX = e.offsetX,
            downY = e.offsetY;

        // ダウンしたので、描画フラグをtrueにする
        drawFlag = true;

        // 座標を保持する
        preX = downX;
        preY = downY;
    });

    $('#my-canvas').mousemove(e => {
        if(!drawFlag) {// 描画中でない
            return;
        }
        // canvasの左上隅を原点とする座標を求める
        const downX = e.offsetX,
            downY = e.offsetY;

        // 1つ前の座標から現在の座標まで線分を描画する
        drawLine(preX, preY, downX, downY);

        // 座標を保持する
        preX = downX;
        preY = downY;
    });

    $('#my-canvas').mouseup(e => {
        // マウスボタンが離されたので、描画フラグをfalseにする
        drawFlag = false;
    });

    $('#my-canvas').mouseout(e => {
        // マウスカーソルがcanvasの外に出たので、描画フラグをfalseにする
        drawFlag = false;
    });

    function drawLine(startX, startY, endX, endY) {
        // コンテキストを取得
        const ctx = $('#my-canvas')[0].getContext('2d');

        // 現在の描画状態を保存する
        ctx.save();   

        ctx.lineCap = 'round';
        ctx.lineWidth = 3;
        ctx.strokeStyle = '#000000';

        ctx.beginPath();				// 現在のパスをリセットする
        ctx.moveTo(startX, startY);		// パスの開始座標を指定する
    	ctx.lineTo(endX, endY);			// 座標を指定してラインを引く
        ctx.stroke();          			// 現在のパスを描画する

        // 描画状態を保存した時点のものに戻す
        ctx.restore();
    }
});
</script>
</head>
<body>
<canvas id="my-canvas" width="500" height="300"></canvas>
</body>
</html>

マウスドラッグで線を引くことができました。
ダウンロード (9).png

#解説
問題12で円をドラッグするプログラムを書きましたが、それに似ています。

使う変数は3つです。

let preX = 0, // 1つ前のX座標
    preY = 0, // 1つ前のY座標
    drawFlag = false;   // 線を描画中か

まずはマウスダウンの処理です。
描画中フラグをtrueにして、現在のカーソルの座標を記憶します。

$('#my-canvas').mousedown(e => {
    // canvasの左上隅を原点とする座標を求める
    const downX = e.offsetX,
        downY = e.offsetY;

    // ダウンしたので、描画フラグをtrueにする
    drawFlag = true;

    // 座標を保持する
    preX = downX;
    preY = downY;
});

次にマウスムーブの処理です。
描画中フラグがtrueのときだけ、1つ前のカーソルの座標から現在のカーソルの座標まで線分を描画します。
現在のカーソルの座標を記憶します。

今まで何かをcanvasに描画するときに毎回canvasをクリアしていましたが
今回はあえてクリアしていません。クリアしても描画結果は同じになるのですが、
クリアしないと以前に引いた線を描画する必要がないため、描画時間が短くなります。

$('#my-canvas').mousemove(e => {
    if(!drawFlag) {// 描画中でない
        return;
    }
    // canvasの左上隅を原点とする座標を求める
    const downX = e.offsetX,
        downY = e.offsetY;

    // 1つ前の座標から現在の座標まで線分を描画する
    drawLine(preX, preY, downX, downY);

    // 座標を保持する
    preX = downX;
    preY = downY;
});

function drawLine(startX, startY, endX, endY) {
    // コンテキストを取得
    const ctx = $('#my-canvas')[0].getContext('2d');

    // 現在の描画状態を保存する
    ctx.save();   

    ctx.lineCap = 'round';
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#000000';

    ctx.beginPath();				// 現在のパスをリセットする
    ctx.moveTo(startX, startY);		// パスの開始座標を指定する
	ctx.lineTo(endX, endY);			// 座標を指定してラインを引く
    ctx.stroke();          			// 現在のパスを描画する

    // 描画状態を保存した時点のものに戻す
    ctx.restore();
}

マウスアップで描画フラグもfalseにして、描画を終了します。
マウスアウトでも同様です。

$('#my-canvas').mouseup(e => {
    // マウスボタンが離されたので、描画フラグをfalseにする
    drawFlag = false;
});

$('#my-canvas').mouseout(e => {
    // マウスカーソルがcanvasの外に出たので、描画フラグをfalseにする
    drawFlag = false;
});
2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?