#問題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>
#解説
問題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;
});