Чтобы отслеживать, что рисуется, многие приложения, такие как приложения для рисования, системы автоматизированного проектирования (САПР) и игры, поддерживают список отображаемых в данный момент объектов. Обычно эти приложения позволяют пользователям манипулировать объектами, отображаемыми в данный момент на экране. Например, в приложении САПР мы можем выбирать, перемещать, масштабировать и т. д. элементы конструкции.
- «Технология HTML5 Canvas Core»
То же самое относится и 实现拖拽
в Canvas. Canvas предоставляет API под названием isPointInPath(x, y)
, чтобы определить, находится ли 点(x, y)
на пути. Возвращает true, если оно находится в пределах пути. Итак, у нас могут быть следующие идеи:
Поддерживайте 数组
, который может описывать каждый путь, и используйте ispointInPath(x, y)
чтобы определить, находится ли выбранная позиция на определенном пути. Если она находится на этом пути, выберите этот путь, выполните операции (перемещение, масштабирование и т. д.). , а затем нарисуйте графику
В этой статье я использую 多边形拖拽为例进行说明
. Демонстрация выглядит следующим образом (причиной отпечатка является программное обеспечение для записи экрана: japanese_ogre:):
CodePen открывается
Как рисовать многоугольники в демо-версии уже было кратко описано ранее, поэтому я не буду снова вдаваться в подробности: Ghost:: Рисование многоугольников на холсте
Объяснение идейНа рисунке ниже дано примерное описание и псевдокод. Идея несложная, но есть некоторые детали, с которыми необходимо разобраться.
Здесь приведена структура кода и отмечены его идеи. Более подробные комментарии к коду находятся в CodePen.
Поскольку эта статья посвящена перетаскиванию, описания рисования будет меньше.
//Функция функции рисования пути многоугольника drawPolygonPath//Определение класса Polygon class Polygon{ ...}//Вернем позицию на холсте в соответствии с функцией события щелчка positoinInCanvas//Получим расстояние по прямой между двумя точками function getDistance// На начальном этапе запишите перетаскивание. Перетаскивание объекта Canvas.onmousedown // Фаза перетаскивания, путь рисования, обводка Canvas.onmousemove // Конечная фаза, обновление положения перетаскиваемого объекта Canvas.onmouseup.Описание ключевых частей
Далее приступаем к обработке ключевых частей и деталей кода.
Как поддерживать массив перетаскиваемых объектовВо время инициализации программы мы определяем массивpolygonArray
полигонмассив = []
Каждый раз, когда рисуется новый многоугольник, новый объект-полигон будет помещен в массив для обслуживания.
const polygon = new Polygon(mouseStart.get('x'), mouseStart.get('y'),sideNum, radius);polygonArray.push(polygon);//Запись объекта пути
В последующих операциях щелчка необходимо на основе соответствующей информации определить, находится ли позиция щелчка на пути.
Как выбрать объект для перетаскивания при нажатии Сначала получите соответствующую позицию canvas中
при нажатии. Мой код использует mouseStart
для записи x
и y
Затем пройдитесь по polygon
в polygonArray
, вызовите polygon.createPath()
во время обхода и используйте isPointInPath()
чтобы определить, есть ли путь в выбранной позиции. Если да, draggingPolygon = polygon
завершает функцию.
const pos =positionInCanvas(e, CanvasLeft, CanvasTop);//Получить положение пикселя на холсте//Записать начальную точку мыши smouseStart.set('x', pos.x);mouseStart.set('y', pos. y);...for (пусть полигон полигона) {polygon.createPath(); (ctx.isPointInPath(mouseStart.get('x'), mouseStart.get('y'))) {draggingPolygon = полигон; } }Расчет при перетаскивании
Эту часть необходимо полностью понять. Рекомендуется выполнять отладку на основе двух console.log(draggingPolygon)
и кода в демонстрационной версии, поскольку мы находимся на этапе mousemove
, и на этом этапе функции запускаются очень часто.
Я стараюсь выразить это ясно словами
Сначала вычислите расстояние от mouseStart
при move
, которое записывается как diff. По оси X находится offsetX
, а по оси Y — offsetY
.
const pos =positionInCanvas(e, CanvasLeft, CanvasTop), diff = new Map([ ['offsetX', pos.x - mouseStart.get('x')], ['offsetY', pos.y - mouseStart.get( 'у')] ]);
Затем запишите centerX
и centerY
текущего объекта перетаскивания, записанный как temp.
пусть tempCenterX = перетаскиваниеPolygon.centerX, tempCenterY = перетаскиваниеPolygon.centerY;
Это трудный для понимания момент. Почему мы должны это записывать? Продолжайте читать, вы будете использовать это позже.
Установите новое центральное положение перетаскиванияPolygon в соответствии со смещением в diff
перетаскиваниеPolygon.centerX += diff.get('offsetX'); draggingPolygon.centerY += diff.get('offsetY');
Затем очистите холст и нарисуйте новые контуры и штрихи.
ctx.clearRect(0, 0, Canvas.width, Canvas.height);for (пусть многоугольник из PolygonArray) { drawPolygonPath(polygon.sideNum, Polygon.radius, Polygon.centerX, Polygon.centerY, ctx.stroke(); );}
Наконец, используются упомянутые выше tempCenterX
и tempCenterY
:
перетаскиваниеPolygon.centerX = tempCenterX; перетаскиваниеPolygon.centerY = tempCenterY;
Почему нам нужно это делать?
Потому что наше перетаскивание 基于多边形的原位置
, и этап mousemove
不能确定函数的最终位置
. Если в этот момент не будет восстановления, произойдет 漂移
, я закомментировал эти две строки кода, и эффект следующий:
Если я не ясно выразился, то рекомендую всем доработать и отладить код.
Обработка после перетаскивания После завершения перетаскивания он находится на этапе mouseup
. На данный момент мы определили окончательное положение перетаскиванияPolygon и можем его обновить. Наконец, для него установлено значение null, чтобы исключить 在没有拖拽多边形情况下,鼠标在画布上移动触发对应代码
const pos = PositionInCanvas(e, CanvasLeft, CanvasTop), offsetMap = new Map([ ['offsetX', pos.x - mouseStart.get('x')], ['offsetY', pos.y - mouseStart.get( 'y')] ]); draggingPolygon.centerX += offsetMap.get('offsetX'); offsetMap.get('offsetY'); draggingPolygon = null;Заключение
На самом деле реализовать эту функцию несложно. Главное — понять концепцию: отслеживание достигается за счет ведения списка отображаемых в данный момент объектов и принятия решений с помощью isPointInPath.
Наконец, приглашаем всех обменяться опытом и поучиться.
Ссылки«Технология HTML5 Canvas Core»
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.