準備
行クリックを検出するには、すべてのパス情報を記録する必要があります。
次の例は、元の投稿で提供されたコードの修正版であり、すべてのストロークを含む配列に (マウス ダウンとマウス ダウンの間の) 各ストロークを記録するストローク レコーダーが含まれています。
簡単にするために、ここではモードを変更するときにマウス クリックをリッスンします。クリック モードでは、ストローク コレクションを反復処理し、以前に記録したパスを再構築してから、マウスの位置がこれらの行のいずれかにあるかどうかを確認します。
コードは、パスを構築する前にヒット領域を使用してオーバーヘッドを削減することで最適化できますが、デモのために必要なコードのみが含まれています。
デモコード
オンラインデモはこちら
記録するには、線/ストロークを保存するものが必要です。
var lines = [], line;
モードを切り替えるときに使用するクリックのイベント リスナーを追加します。通常、代わりに mousedown/up イベントを共有することに注意してください。
canvas.addEventListener("click", checkLine, false);
行をより「クリック可能」にするために、ここでは太い線幅を使用します (デモ用に修正)。
context.lineWidth = 3;
記録するには、既存のコールバックを変更する必要があります。また、マウスを動かすたびに線が重なって再描画されるバグもあり、線が長いと最終的に描画が遅くなります。
また、キャンバスに対して相対的になるようにマウスの位置を調整する必要があります。
function startDraw(event) {
/// if we are in "click" mode exit from here (for demo)
if (mode.checked === true) return;
/// adjust mouse position
var pos = mouseXY(canvas, event);
drawing = true;
/// start a new path
context.beginPath();
context.moveTo(pos.x, pos.y);
/// create a new stroke and push first position to it
line = [];
line.push([pos.x, pos.y]);
}
線全体を再描画しないように、描画する部分ごとにパスをリセットする必要があります (最終的なレンダリング/再描画では、もちろん線を一度に再描画しますが、描画中には再描画しません)。
function continueDraw(event) {
if (drawing) {
/// adjust mouse position
var pos = mouseXY(canvas, event);
/// complete one line segment started in mouse down
context.lineTo(pos.x, pos.y);
context.stroke();
/// reset path and start from where we ended this line
context.beginPath();
context.moveTo(pos.x, pos.y);
/// store current point to stroke/line
line.push([pos.x, pos.y]);
}
}
最後に行が終了したら、ストロークを保存します。
function endDraw(event) {
if (drawing) {
var pos = mouseXY(canvas, event);
context.lineTo(pos.x, pos.y);
context.stroke();
drawing = false;
/// push stroke/line to line stack
lines.push(line);
}
}
これを使用してマウスの位置を調整します::
function mouseXY(c, e) {
var r = c.getBoundingClientRect();
return {x: e.clientX - r.left, y: e.clientY - r.top};
}
ラインクリックの確認
行をチェックするには、行コレクションを繰り返し処理し、各行をパスとして再構築する必要があります。これらのパスを描画する必要がないため、速度は問題ありません。パスが再構築されると、以下を使用して、パスに対して調整されたマウスの位置を確認しますisPointInStroke
。
function checkLine(e) {
if (mode.checked === false) return;
var i = 0, line, l, p, pos = mouseXY(canvas, e);
/// make sure stroke has same width as originally recorded
context.lineWidth = 3;
/// loop through line collection
for(; line = lines[i]; i++) {
/// reset path
context.beginPath();
/// begin stroke
context.moveTo(line[0][0], line[0][1]);
/// iterate through each point stored
for(l = 1; p = line[l]; l++) {
/// add a line
context.lineTo(p[0], p[1]);
}
/// then we check the point
if (context.isPointInStroke(pos.x, pos.y) === true) {
alert('hit line ' + i); /// show "ID" of line clicked
return;
}
}
}
複雑に重なっている線でも問題なく検出できます。

(はい、知っています! 私はいつでもダリとムンクを倒すことができます! Xp )