В модели обработки взаимодействий в браузере каждое пользовательское действие — движение мыши, клик, касание экрана, прокрутка — формируется как объект события. В D3.js этот объект выступает центральным источником информации о контексте взаимодействия: тип действия, координаты указателя, целевой элемент, состояние модификаторов клавиатуры.
Современные версии D3 (v6+) опираются на стандартный механизм событий
браузера, где объект события передаётся напрямую в обработчик. Это
устранило необходимость в глобальной переменной d3.event,
использовавшейся в более ранних версиях.
Основные свойства объекта события:
type — тип события (click,
mousemove, pointermove и т.д.)target — DOM-элемент, на котором произошло событиеcurrentTarget — элемент, к которому привязан
обработчикclientX, clientY — координаты относительно
окна браузераpageX, pageY — координаты относительно
документаscreenX, screenY — координаты относительно
экранаaltKey, ctrlKey, shiftKey,
metaKey — состояние клавиш-модификаторовbutton — нажатая кнопка мышиВ контексте визуализаций D3 особое значение имеют координаты указателя, поскольку они используются для сопоставления действий пользователя с геометрией SVG или Canvas-сцены.
Обработчики событий в D3 задаются через .on():
d3.select("svg")
.on("click", function(event) {
console.log(event.type);
console.log(event.clientX, event.clientY);
});
Первый аргумент функции обработчика — объект события. Второй важный
контекст — this, указывающий на DOM-элемент, к которому
привязан обработчик. Внутри D3 часто используется
event.currentTarget, так как он более явно отражает элемент
привязки.
Одной из ключевых сложностей интерактивной визуализации является преобразование координат события в систему координат графика.
Событие мыши предоставляет координаты в экранной системе (viewport), тогда как элементы SVG и Canvas могут иметь собственную локальную систему координат, зависящую от:
viewBox SVGtranslate, scale,
rotate)<g>Прямое использование event.clientX и
event.clientY приводит к некорректному позиционированию в
большинстве случаев.
Функция d3.pointer() предназначена для преобразования
координат события в локальную систему координат заданного
контейнера.
Сигнатура:
d3.pointer(event, target)
event — объект события браузераtarget — DOM-элемент, относительно которого вычисляются
координатыВозвращаемое значение — массив из двух чисел:
[x, y]
где x и y — координаты указателя в системе
координат целевого элемента.
Внутренне d3.pointer() выполняет цепочку
преобразований:
clientX,
clientY)Это позволяет абстрагироваться от сложных вычислений, связанных с DOM-структурой и графическими преобразованиями.
Типичный сценарий — обработка клика внутри SVG-области:
const svg = d3.select("svg");
svg.on("click", function(event) {
const [x, y] = d3.pointer(event, this);
console.log("SVG координаты:", x, y);
});
Здесь this указывает на SVG-элемент, что делает
координаты согласованными с его системой координат.
SVG часто содержит вложенные группы <g> с
трансформациями:
<svg>
<g transform="translate(50,50) scale(2)">
<circle cx="0" cy="0" r="10"></circle>
</g>
</svg>
При клике внутри такого элемента прямое использование экранных
координат не даёт корректного результата. d3.pointer()
учитывает матрицу трансформации и возвращает координаты уже в
пространстве группы.
d3.select("g")
.on("click", function(event) {
const coords = d3.pointer(event, this);
console.log(coords);
});
При использовании d3.zoom() происходит динамическое
изменение трансформации контейнера. Это добавляет дополнительный слой
сложности, так как координаты события должны учитываться относительно
текущего масштаба.
const zoom = d3.zoom()
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
svg.call(zoom);
При обработке кликов внутри масштабируемой группы
d3.pointer() автоматически учитывает текущую матрицу
трансформации, возвращая координаты в уже преобразованном
пространстве.
В Canvas нет встроенной системы координат элементов, поэтому преобразование выполняется относительно bounding box элемента:
const canvas = d3.select("canvas");
canvas.on("mousemove", function(event) {
const [x, y] = d3.pointer(event, this);
console.log(x, y);
});
Здесь координаты соответствуют пикселям внутри canvas-элемента, без дополнительной иерархии DOM.
Без d3.pointer() преобразование координат требует ручной
обработки:
const rect = svg.node().getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
Однако этот подход не учитывает SVG-трансформации, что делает его ограниченным.
d3.pointer() расширяет эту модель, добавляя
поддержку:
В современных браузерах pointer events унифицируют мышь и касания.
Однако при работе с touch или legacy mouse events
d3.pointer() одинаково корректно обрабатывает
координаты.
selection.on("touchmove", function(event) {
const [x, y] = d3.pointer(event, this);
});
При множественных касаниях используется первый touch-point, если не задан иной режим обработки.
Часто координаты требуются внутри цепочки D3:
d3.selectAll("circle")
.on("mousemove", function(event, d) {
const [x, y] = d3.pointer(event, this);
});
Каждый элемент получает локальные координаты относительно себя, что особенно важно при построении интерактивных графиков, где элементы могут иметь разные трансформации.
Второй аргумент d3.pointer(event, target) критически
влияет на результат. Разные значения target дают разные
системы координат:
this (DOM-элемент) — локальные координаты элементаsvg.node() — координаты всей SVG-сцены<g> — координаты внутри
группыПример:
const [x1, y1] = d3.pointer(event, svg.node());
const [x2, y2] = d3.pointer(event, g.node());
Эти координаты будут различаться, так как относятся к разным системам.
В старых версиях D3 использовалась глобальная переменная:
d3.event
Она содержала текущий объект события и использовалась вместе с:
d3.mouse(node)
Современная модель:
d3.event удаленаd3.mouse() заменена на d3.pointer()Это делает систему более предсказуемой и совместимой с нативным DOM API.
window
вместо SVG-элемента)Корректная работа требует строгого разделения:
В интерактивных визуализациях координаты, полученные через
d3.pointer(), становятся базой для:
Каждый из этих сценариев опирается на единый принцип: преобразование глобального события в локальное пространство визуализации.