Canvas нужно сделать кликабельным

Есть canvas 1000 на 1000. Как обработать проведение по нему мышкой с зажатой ЛКМ (нужно знать x и y наведения)?


Ответы (1 шт):

Автор решения: De.Minov

Для отлавливания позиции курсора используйте обработчик mousemove, в нём вы можете получить позицию курсора на экране, за счёт возвращаемого события MouseEvent, в котором содержатся свойство clientX и clientY:

element.addEventListener('mousemove', (event) => {
  console.log(event.clientX, event.clientY) // Выведет позицию курсора по X и Y
})

Но данное событие будет выполняться постоянно.
Чтобы это происходило лишь тогда, когда зажата клавиша ЛКМ, нужно создать переменную, которая будет разрешать выполнять какие-то действия при событии mousemove.

Для этого воспользуемся обработчиком mousedown - это событие отрабатывает когда произошло нажатие на кнопку мыши. Событие возвращает MouseEvent, в котором содержится свойство button, где значение 0 - является клавишей ЛКМ

element.addEventListener('mousedown', (event) => {
  console.log(event.button === 0) // выведет TRUE если нажата ЛКМ, в остальных случаях FALSE
})

Чтобы поменять значение переменной на обратное, используем событие, которое отработает, когда клавиша мыши будет отпущена - mouseup.

Так же, советую, передавать функцию, которая будет передаваться в mouseup, в событие mouseout, чтобы прекратить действие, когда курсор выйдет за пределы элемента, в вашем случае - это Canvas.


Ниже я добавляю пример простой "рисовалки" на Canvas, где реализована нужная автору механика.

const can = document.querySelector('#can') // Получаем элемент canvas
const ctx = can.getContext('2d') // Получаем контекст canvas
let isDraw = false // флаг, благодаря которому будем отслеживать когда надо рисовать, а когда нет

// Надстройки
ctx.lineJoin = 'round' // форма вершин
ctx.lineCap = 'round' // форма концов линии
ctx.lineWidth = 5 // толщина линии

// Функция отрисовки линии
const CanvasDraw = (event) => {
  const rect = can.getBoundingClientRect() // получаем позицию canvas относительно вьюпорта
  const x = event.clientX - rect.left // Получаем позицию курсора на экране по X, вычитаем отступ от canvas от края экрана, получаем X позицию курсора на canvas
  const y = event.clientY - rect.top // Аналогично с вычислением выше
  ctx.lineTo(x, y) // выставляем новую позицию линию, по позиции курсора, от предыдущей точки
  ctx.stroke() // отрисовываем линию
}

// Функция начала рисования
const CanvasDrawStart = (event) => {
  // Определяем, что нажата именно ЛКМ
  if(event.button === 0) {
    isDraw = true // меняем флаг
    CanvasDraw(event) // отрисосываем первую точку
  }
}

// Функция для отключения рисования
const CanvasDrawStop = (event) => {
  isDraw = false // меняем флаг
  ctx.beginPath() // закрываем предыдущие пути, чтобы можно было рисовать новые
}

can.addEventListener('mousedown', CanvasDrawStart) // вешаем обработчик при нажатии кнопки мыши
can.addEventListener('mousemove', (event) => isDraw ? CanvasDraw(event) : false) // вешаем обработчик при движении мыши
can.addEventListener('mouseup', CanvasDrawStop) // вешаем обработчик при отпускании клавиши мыши
can.addEventListener('mouseout', CanvasDrawStop) // вешаем обработчик, если вышли за границу canvas
body {
  background-color: #f2f2f2
}

canvas {
  background-color: #fff;
}
<canvas id="can" width="1000" height="1000"></canvas>

→ Ссылка