在复杂的画布形状上单击事件,而无需使用外部库 [英] Click events on complex canvas shapes without recourse to external libraries

查看:89
本文介绍了在复杂的画布形状上单击事件,而无需使用外部库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在单个画布元素上实现对多个复杂形状的点击检测,类似于 CanvasRenderingContext2D.isPointInPath()所实现的.

I'd like to implement click detection for multiple complex shapes on a single canvas element similar to that as realized by CanvasRenderingContext2D.isPointInPath().

以下强制性示例代码.

HTML:

<canvas id="canvas"></canvas>
<p>In path: <code id="result">false</code></p>

JS:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const result = document.getElementById('result');

ctx.beginPath();
ctx.moveTo(25, 25);
ctx.lineTo(105, 25);
ctx.lineTo(25, 105);
ctx.fill();

ctx.beginPath();
ctx.moveTo(125, 45);
ctx.lineTo(45, 125);
ctx.lineTo(125, 125);
ctx.lineTo(205, 45);
ctx.closePath();
ctx.fill();

window.addEventListener('mousemove', e => {
result.innerText = `${ctx.isPointInPath(e.clientX, e.clientY)} X: ${e.clientX} Y: ${e.clientY}`;
});

虽然上述方法对最后绘制的形状效果很好,但我希望能够对所有先前绘制的形状执行相同的检查.

While the above works well for the last drawn shape, I'd like to be able to perform the same check for any previously drawn shapes.

我正在从事的项目涉及在等轴测图上选择不同的图块,因此一旦单击该图块,我将尽可能多地接收有关所选图块的信息.

The project I am working on involves selecting different tiles on an isometric map, so I would like to receive as much information about the selected tile as I can once that tile is clicked on.

由于我打算绘制的形状数量多,我宁愿不必求助于渲染SVG.另外,外部库是不希望的,我很犹豫要为我在可见"画布上绘制的每个形状绘制一个伪画布,以便能够检测到点击.除了等待受灾地区脱离实验状态外,还有哪些其他选择?

I'd rather not have to resort to rendering SVGs due to the amount of shapes I intend to draw. Also, external libraries are undesired and I'm hesitant to draw a pseudo canvas for every shape I draw on the 'visible' canvas just to be able to detect clicks. What alternatives are out there other than waiting for hit regions to come out of experimental status?

我在这里遇到了一个类似但最终不同的问题:画布上的复杂形状选择

I came across a similar, but ultimately different question here: complex shape selection on canvas

推荐答案

isPointInPath accepts a Path2D object as optional first argument.

一个简单的方法是为每个形状创建此类Path2D对象.
它甚至可以简化您的绘图操作,因为 fill() stroke()也可以接受以下对象:

So an easy way is to create such Path2D objects for each of your shapes.
It can even ease your drawing operations, since fill() and stroke() also accept these objects:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const result = document.getElementById('result');

const shape1 = new Path2D();
shape1.moveTo(25, 25);
shape1.lineTo(105, 25);
shape1.lineTo(25, 105);

const shape2 = new Path2D();
shape2.moveTo(125, 45);
shape2.lineTo(45, 125);
shape2.lineTo(125, 125);
shape2.lineTo(205, 45);
shape2.closePath();

// to render it
ctx.fill(shape1);
ctx.fill(shape2);

canvas.addEventListener('mousemove', e => {
result.textContent = `
  shape1: ${ctx.isPointInPath(shape1, e.offsetX, e.offsetY)}
  shape2: ${ctx.isPointInPath(shape2, e.offsetX, e.offsetY)}
  X: ${e.offsetX} Y: ${e.offsetY}`;
});

.log { display: inline-block; vertical-align: top}

<canvas id="canvas"></canvas>
<div class="log">In path: <pre id="result">false</pre></div>

这篇关于在复杂的画布形状上单击事件,而无需使用外部库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆