Как добавить простой обработчик событий onclick к элементу холста?
Я программист на Java, но примерно за десять лет смотрю впервые на некоторые вещи, связанные с JavaScript / HTML5. Я совершенно не понимаю, того, что наверное должно быть самым простым.
В качестве примера, я просто хотел что-то нарисовать и добавить к нему обработчик событий. Я уверен, что делаю что-то глупое, но я искал повсюду, и ничего из предложенного (например, ответ на этот вопрос:
Add onclick property to input with JavaScript для ввода с помощью JavaScript) не работает.
Мой код ниже. Вы увидите несколько прокомментированных строк, и в конце каждой будет описание того, что не происходит или происходит.
Какой здесь правильный синтаксис?
<html>
<body>
<canvas id="myCanvas" width="300" height="150"/>
<script language="JavaScript">
var elem = document.getElementById('myCanvas');
// elem.onClick = alert("hello world"); - displays alert without clicking
// elem.onClick = alert('hello world'); - displays alert without clicking
// elem.onClick = "alert('hello world!')"; - does nothing, even with clicking
// elem.onClick = function() { alert('hello world!'); }; - does nothing
// elem.onClick = function() { alert("hello world!"); }; - does nothing
var context = elem.getContext('2d');
context.fillStyle = '#05EFFF';
context.fillRect(0, 0, 150, 100);
</script>
</body>
Свободный перевод вопроса How do I add a simple onClick event handler to a canvas element? от участника @Jer.
Ответы (1 шт):
2021:
Чтобы создать отслеживаемый элемент, вы должны использовать метод Path2D().
Вы должны прослушивать события мыши на своем холсте, чтобы получить координаты курсора мыши, а затем использовать CanvasRenderingContext2D.isPointInPath() или CanvasRenderingContext2D.isPointInStroke (), чтобы точно проверить, находится ли мышь над вашим элементом.
IsPointInPath:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Создать окружность
const circle = new Path2D();
circle.arc(150, 75, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circle);
// слушать события мыши
canvas.addEventListener('mousemove', function(event) {
// Check whether point is inside circle
if (ctx.isPointInPath(circle, event.offsetX, event.offsetY)) {
ctx.fillStyle = 'green';
}
else {
ctx.fillStyle = 'red';
}
// Нарисовать окружность
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fill(circle);
});
<canvas id="canvas"></canvas>
IsPointInStroke:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Создать эллипс
const ellipse = new Path2D();
ellipse.ellipse(150, 75, 40, 60, Math.PI * .25, 0, 2 * Math.PI);
ctx.lineWidth = 25;
ctx.strokeStyle = 'red';
ctx.fill(ellipse);
ctx.stroke(ellipse);
// Слушайте движения мыши
canvas.addEventListener('mousemove', function(event) {
// Проверить, находится ли точка внутри обводки эллипса
if (ctx.isPointInStroke(ellipse, event.offsetX, event.offsetY)) {
ctx.strokeStyle = 'green';
}
else {
ctx.strokeStyle = 'red';
}
// Рисовать эллипс
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fill(ellipse);
ctx.stroke(ellipse);
});
<canvas id="canvas"></canvas>
Пример с несколькими элементами:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const circle = new Path2D();
circle.arc(50, 75, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circle);
const circletwo = new Path2D();
circletwo.arc(200, 75, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circletwo);
// слушать события мыши
canvas.addEventListener('mousemove', function(event) {
// Проверить, находится ли точка внутри круга
if (ctx.isPointInPath(circle, event.offsetX, event.offsetY)) {
ctx.fillStyle = 'green';
ctx.fill(circle);
}
else {
ctx.fillStyle = 'red';
ctx.fill(circle);
}
if (ctx.isPointInPath(circletwo, event.offsetX, event.offsetY)) {
ctx.fillStyle = 'blue';
ctx.fill(circletwo);
}
else {
ctx.fillStyle = 'red';
ctx.fill(circletwo);
}
});
html {cursor: crosshair;}
<canvas id="canvas"></canvas>
Если у вас есть список проверяемых динамических элементов, вы можете проверять их в цикле, например:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
var elementslist = []
const circle = new Path2D();
circle.arc(50, 75, 30, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circle);
const circletwo = new Path2D();
circletwo.arc(150, 75, 30, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circletwo);
const circlethree = new Path2D();
circlethree.arc(250, 75, 30, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circlethree);
elementslist.push(circle,circletwo,circlethree)
document.getElementById("canvas").addEventListener('mousemove', function(event) {
event = event || window.event;
var ctx = document.getElementById("canvas").getContext("2d")
for (var i = window.elementslist.length - 1; i >= 0; i--){
if (window.elementslist[i] && ctx.isPointInPath(window.elementslist[i], event.offsetX, event.offsetY)) {
document.getElementById("canvas").style.cursor = 'pointer';
ctx.fillStyle = 'orange';
ctx.fill(window.elementslist[i]);
return
} else {
document.getElementById("canvas").style.cursor = 'default';
ctx.fillStyle = 'red';
for (var d = window.elementslist.length - 1; d >= 0; d--){
ctx.fill(window.elementslist[d]);
}
}
}
});
<canvas id="canvas"></canvas>
Источники:
CanvasRenderingContext2D.isPointInPath()
CanvasRenderingContext2D.isPointInStroke()