Реактивный DataV: оптимизация 10k+ точек с event-driven аннотациями и hit-тестингом
Реактивный DataV: оптимизация 10k+ точек с event-driven аннотациями и hit-тестингом Когда на графике 10 000+ точек, часто выбирают: производительность или интерактивность. Прямой рендер в SVG тормозит, Canvas летает, но теряет hover и click. Это ложный компромисс. Гибридный подход Решение — Canvas для рендера точек (никаких DOM-узлов, только пиксели). Hover и click выносятся в event-driven аннотации через raycasting. Считай только при движении мыши, а не на каждый фрейм. Ленивые аннотации и кеширование Рендери только те аннотации, которые попадают в viewport, и кешируй результат. Иначе каждый чих дергает рендер на 10k точках. Пример hit-тестинга Без фреймворков, на TypeScript: class ScatterPlot { handleMouseMove(e) { for (const p of this.points) { if (Math.abs(mouseX - p.x) <= p.r * 2 && Math.abs(mouseY - p.y) <= p.r * 2) { if (Math.hypot(mouseX - p.x, mouseY - p.y) <= p.r) { this.showAnnotation(i); return; } } } } showAnnotation(index) { requestAnimationFrame(() => this.renderAnnotationLayer()); } } Сначала проверка по bounding box, потом по расстоянию. Для 10k точек O(n) срабатывает за пару миллисекунд. QuadTree даёт O(log n), но не всегда нужен. Предупреждение о типичной ошибке Главный подвох: не забудь сбросить аннотацию при уходе мыши с точки. Иначе график зависнет с подписями на все 10k, и пользователь решит, что интерфейс сломался. Вывод: Event-driven аннотации с hit-тестингом — это trade-off между точностью интерактивности и производительностью рендера, где Canvas даёт скорость, а raycasting сохраняет UX.