Tolerance и точность попадания

В Paper.js точность попадания на объекты (hit testing) играет ключевую роль при взаимодействии с векторными элементами. Основной инструмент для этого — Tolerance. Этот параметр определяет, на каком расстоянии от кривой или точки система будет считать, что курсор или точка «попала» на объект.


Настройка Tolerance

Tolerance задается через свойство project.hitTolerance. Оно определяет максимальное расстояние в пикселях между курсором и объектом для успешного срабатывания hit test:

project.hitTolerance = 5; // Установка tolerance в 5 пикселей
  • Малые значения (0–2 пикселя) обеспечивают высокую точность попадания, но усложняют взаимодействие с тонкими объектами.
  • Большие значения (5–10 пикселей и выше) делают интерфейс более «дружелюбным», особенно при работе с кривыми и сложными формами.

Методы hitTest

Основной метод для проверки попадания — hitTest(point, options). Он принимает объект options, где tolerance может быть задан локально, независимо от глобального значения проекта:

var hitResult = path.hitTest(event.point, {
    tolerance: 10,
    fill: true,
    stroke: true,
    segments: true,
    handles: true
});

Ключевые параметры:

  • fill: проверка попадания внутрь заливки объекта
  • stroke: проверка попадания по контуру
  • segments: проверка попадания на узлы (segments)
  • handles: проверка попадания на управляющие точки кривых
  • tolerance: локальная настройка точности (перекрывает project.hitTolerance)

Принципы точности попадания

  1. Расстояние до кривой или линии вычисляется как минимальное перпендикулярное расстояние от точки до сегмента.
  2. Попадание на узел (segment) учитывает радиус, равный tolerance.
  3. Попадание на ручки (handle) также использует Tolerance, что упрощает выбор управляющих точек при редактировании кривых.

Пример визуализации tolerance для кривой:

var path = new Path();
path.strokeColor = 'black';
path.add(new Point(50, 50));
path.add(new Point(200, 150));

path.onMouseM ove = function(event) {
    var hit = path.hitTest(event.point, { stroke: true, tolerance: 10 });
    if(hit) {
        path.strokeColor = 'red';
    } else {
        path.strokeColor = 'black';
    }
}

При движении курсора в пределах 10 пикселей от линии цвет кривой меняется, что наглядно показывает работу tolerance.


Сочетание глобального и локального Tolerance

project.hitTolerance устанавливает общую точность для всех операций hitTest без явной передачи локальных параметров. Если необходимо изменить точность только для одного объекта или одного события, используется локальный параметр:

project.hitTolerance = 2;

var hit = path.hitTest(event.point, { tolerance: 15 });

В этом случае глобальная точность мала, но конкретное hitTest событие проверяет попадание в радиусе 15 пикселей.


Практические рекомендации

  • Для редактирования кривых лучше использовать малое значение, чтобы не срабатывать на соседние сегменты.
  • Для интерфейсов с мелкими элементами и кликабельными объектами — увеличивать tolerance, чтобы повысить удобство.
  • При сложных hitTest проверках можно комбинировать fill, stroke и segments, чтобы достичь оптимального баланса точности и удобства.

Влияние Tolerance на производительность

Большое значение tolerance может увеличить количество проверок при hitTest на сложных объектах, особенно если в проекте сотни сегментов. В таких случаях рекомендуется:

  • Ограничивать проверку только нужными слоями или группами объектов.
  • Использовать локальный tolerance вместо глобального, если высокая точность нужна только для конкретных операций.
  • Минимизировать активные события mouseMove, проверяя hitTest только при необходимости.

Итоговое использование

Правильная настройка tolerance обеспечивает:

  • Точное взаимодействие с объектами
  • Удобство выбора сегментов и ручек кривых
  • Контролируемую производительность при большом количестве объектов

Использование комбинации глобального и локального tolerance, а также параметров fill, stroke, segments и handles позволяет создавать гибкие и отзывчивые интерфейсы в Paper.js, адаптированные под конкретные задачи.