d3-drag
Перетаскивание — популярный и лёгкий в освоении способ взаимодействия с помощью указателя: переместите указатель на объект, нажмите и удерживайте, чтобы его взять, «перетащите» объект в новое место и отпустите, чтобы «опустить». Поведение перетаскивания в D3 обеспечивает удобную, но гибкую абстракцию для включения взаимодействия перетаскивания на выборках. Например, вы можете использовать d3-drag, чтобы облегчить взаимодействие с графом с силовым направлением или симуляцией сталкивающихся кругов:
Вы также можете использовать d3-drag для реализации пользовательских элементов интерфейса, таких как ползунок. Но поведение перетаскивания не ограничивается только перемещением элементов; существует множество способов реагировать на жест перетаскивания. Например, вы можете использовать его для выделения элементов в диаграмме рассеяния или для рисования линий на холсте:
Поведение перетаскивания можно комбинировать с другими поведениями, например, с d3-zoom для масштабирования.
Поведение перетаскивания не зависит от DOM, поэтому вы можете использовать его с SVG, HTML или даже холстом! И вы можете расширить его с помощью расширенных техник выбора, таких как наложение Вороного или поиск ближайшей цели:
Лучше всего, поведение перетаскивания автоматически объединяет ввод мыши и сенсорного ввода и избегает особенностей браузера. Когда события указателя станут более широко доступны, поведение перетаскивания также будет поддерживать их.
Установка
Если вы используете NPM, npm install d3-drag. В противном случае, скачайте последнюю версию. Вы также можете загрузить её напрямую с d3js.org, как отдельную библиотеку или как часть D3 4.0. Поддерживаются среды AMD, CommonJS и vanilla. В vanilla экспортируется глобальная переменная d3:
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script> <script src="https://d3js.org/d3-selection.v1.min.js"></script> <script src="https://d3js.org/d3-drag.v1.min.js"></script> <script> var drag = d3.drag(); </script>
Попробуйте d3-drag в вашем браузере.
Ссылка на API
В этой таблице описывается, как поведение перетаскивания интерпретирует события:
| Событие | Элемент прослушивания | Событие перетаскивания | Предотвратить по умолчанию? |
|---|---|---|---|
| mousedown⁵ | выборка | начало | нет¹ |
| mousemove² | окно¹ | перетаскивание | да |
| mouseup² | окно¹ | конец | да |
| dragstart² | окно | - | да |
| selectstart² | окно | - | да |
| click³ | окно | - | да |
| touchstart | выборка | начало | нет⁴ |
| touchmove | выборка | перетаскивание | да |
| touchend | выборка | конец | нет⁴ |
| touchcancel | выборка | конец | нет⁴ |
Распространение всех потребленных событий немедленно останавливается. Если вы хотите предотвратить некоторые события от инициирования жеста перетаскивания, используйте drag.filter.
¹ Необходимо для захвата событий вне iframe; см. #9.
² Применимо только во время активного жеста, основанного на мыши; см. #9.
³ Применимо только сразу после некоторых жестов, основанных на мыши; см. drag.clickDistance.
⁴ Необходимо для эмуляции клика при вводе сенсорного ввода; см. #9.
⁵ Игнорируется, если в течение 500 мс после завершения жеста сенсорного ввода; предполагает эмуляцию клика.
d3.drag() Источник
Создаёт новое поведение перетаскивания. Возвращаемое поведение, drag, является и объектом, и функцией и обычно применяется к выбранным элементам через selection.call.
drag(selection) Источник
Применяет это поведение перетаскивания к указанной выборке. Эта функция обычно не вызывается непосредственно, а вместо этого вызывается через selection.call. Например, для создания поведения перетаскивания и его применения к выборке:
d3.selectAll(".node").call(d3.drag().on("start", started)); Внутренне, поведение перетаскивания использует selection.on для привязки необходимых обработчиков событий для перетаскивания. Обработчики используют имя .drag, поэтому вы можете впоследствии отвязать поведение перетаскивания следующим образом:
selection.on(".drag", null); Применение поведения перетаскивания также устанавливает стиль -webkit-tap-highlight-color в прозрачный, отключая выделение нажатия на iOS. Если вы хотите другой цвет выделения нажатия, удалите или повторно примените этот стиль после применения поведения перетаскивания.
drag.container([container]) Источник
Если container указан, устанавливает функцию доступа к контейнеру в указанный объект или функцию и возвращает поведение перетаскивания. Если container не указан, возвращает текущую функцию доступа к контейнеру, которая по умолчанию:
function container() {
return this.parentNode;
} Контейнер жеста перетаскивания определяет систему координат последующих событий перетаскивания, влияя на event.x и event.y. Элемент, возвращаемый функцией доступа к контейнеру, затем передаётся в d3.mouse или d3.touch, соответственно, для определения локальных координат указателя.
Функция доступа к контейнеру по умолчанию возвращает родительский узел элемента в исходной выборке (см. drag), который получил событие ввода. Это часто подходит при перетаскивании элементов SVG или HTML, так как эти элементы обычно позиционируются относительно родителя. Для перетаскивания графических элементов с холстом, однако, вы можете переопределить контейнер как сам начальный элемент:
function container() {
return this;
} В качестве альтернативы, контейнер может быть задан напрямую, например drag.container(canvas).
drag.filter([filter]) Источник
Если filter указан, устанавливает фильтр в указанную функцию и возвращает поведение перетаскивания. Если filter не указан, возвращает текущий фильтр, который по умолчанию:
function filter() {
return !d3.event.button;
} Если фильтр возвращает ложное значение, событие инициализации игнорируется, и никакие жесты перетаскивания не начинаются. Таким образом, фильтр определяет, какие события ввода игнорируются; фильтр по умолчанию игнорирует события mousedown на дополнительных кнопках, поскольку эти кнопки обычно предназначены для других целей, таких как контекстное меню.
drag.touchable([touchable]) Источник
Если touchable указан, устанавливает детектор сенсорного ввода в указанную функцию и возвращает поведение перетаскивания. Если touchable не указан, возвращает текущий детектор сенсорного ввода, который по умолчанию:
function touchable() {
return "ontouchstart" in this;
} Обработчики событий сенсорного ввода регистрируются только в том случае, если детектор возвращает истину для соответствующего элемента, когда поведение перетаскивания применено. Детектор по умолчанию хорошо работает для большинства браузеров, способных к сенсорному вводу, но не для всех; например, эмулятор мобильного устройства Chrome не обнаруживает его.
drag.subject([subject]) Источник
Если subject указан, устанавливает функцию доступа к объекту в указанный объект или функцию и возвращает поведение перетаскивания. Если subject не указан, возвращает текущую функцию доступа к объекту, которая по умолчанию:
function subject(d) {
return d == null ? {x: d3.event.x, y: d3.event.y} : d;
} Объект жеста перетаскивания представляет вещь, которую перетаскивают. Он вычисляется при получении события инициализации ввода, такого как mousedown или touchstart, непосредственно перед началом жеста перетаскивания. Затем объект предоставляется как event.subject в последующих событиях перетаскивания для этого жеста.
Объект по умолчанию — это данные элемента в исходной выборке (см. drag), который получил событие начального ввода; если эти данные не определены, создаётся объект, представляющий координаты указателя. При перетаскивании кругов в SVG объектом по умолчанию является данные круга, который перетаскивается. С холстом объектом по умолчанию являются данные элемента холста (независимо от того, где вы кликаете на холсте). В этом случае более подходящей будет настраиваемая функция доступа к объекту, например, та, которая выбирает ближайший круг к мыши в заданном радиусе поиска:
function subject() {
var n = circles.length,
i,
dx,
dy,
d2,
s2 = radius * radius,
circle,
subject;
for (i = 0; i < n; ++i) {
circle = circles[i];
dx = d3.event.x - circle.x;
dy = d3.event.y - circle.y;
d2 = dx * dx + dy * dy;
if (d2 < s2) subject = circle, s2 = d2;
}
return subject;
} (При необходимости это можно ускорить с помощью quadtree.find.)
Возвращаемый объект должен быть объектом, который предоставляет x и y свойства, чтобы относительное положение объекта и указателя сохранялось во время жеста перетаскивания. Если объект равен null или undefined, для этого указателя не начинается никакой жест перетаскивания; однако, другие начальные касания могут всё ещё начать жесты перетаскивания. См. также drag.filter.
Изменение объекта, к которому применяется жест перетаскивания, после начала жеста запрещено. Доступ к объекту выполняется с тем же контекстом и аргументами, что и слушатели selection.on: текущий элемент данных d и индекс i, с контекстом this в качестве текущего элемента DOM. Во время вычисления аксессора объекта d3.event представляет собой событие перетаскивания перед началом drag event. Используйте event.sourceEvent для доступа к инициирующему событию ввода и event.identifier для доступа к идентификатору касания. Значения event.x и event.y относительны к контейнеру и вычисляются с помощью d3.mouse или d3.touch соответственно.
drag.clickDistance([distance]) Source
Если distance задан, устанавливается максимальное расстояние, на которое мышь может перемещаться между нажатием и отпусканием левой кнопки мыши, которое приведет к последующему событию клика. Если в любой момент между нажатием и отпусканием левой кнопки мыши мышь находится на расстоянии не менее distance от своего положения при нажатии, событие клика после отпускания будет подавлено. Если distance не задан, возвращается текущий порог расстояния, который по умолчанию равен нулю. Порог расстояния измеряется в клиентских координатах (event.clientX и event.clientY).
drag.on(typenames, [listener]) Source
Если listener указан, устанавливает обработчик событий для указанных typenames и возвращает поведение перетаскивания. Если для такого же типа и имени уже был зарегистрирован обработчик событий, существующий обработчик удаляется перед добавлением нового. Если listener равен null, удаляются текущие обработчики событий для указанных typenames, если таковые имеются. Если listener не указан, возвращается первый текущий назначенный обработчик, соответствующий указанным typenames, если таковой имеется. При отправке указанного события каждый listener вызывается с тем же контекстом и аргументами, что и слушатели selection.on: текущий элемент данных d и индекс i, с контекстом this в качестве текущего элемента DOM.
typenames — это строка, содержащая один или несколько typename, разделенных пробелами. Каждый typename — это type, за которым необязательно следует точка (.) и name, такие как drag.foo и drag.bar; имя позволяет регистрировать несколько слушателей для одного и того же type. type должен быть одним из следующих:
-
start— после того, как новый указатель становится активным (при нажатии левой кнопкой мыши или touchstart). -
drag— после перемещения активного указателя (при движении мыши или touchmove). -
end— после того, как активный указатель становится неактивным (при отпускании левой кнопки мыши, touchend или touchcancel).
См. dispatch.on для получения дополнительной информации.
Изменения зарегистрированных слушателей через drag.on во время жеста перетаскивания не влияют на текущий жест перетаскивания. Вместо этого необходимо использовать event.on, который также позволяет регистрировать временных слушателей событий для текущего жеста перетаскивания. Отдельные события отправляются для каждого активного указателя во время жеста перетаскивания. Например, если одновременно перетаскиваются несколько объектов с несколькими пальцами, событие начала отправляется для каждого пальца, даже если оба пальца начинают касаться одновременно. См. События перетаскивания для получения дополнительной информации.
d3.dragDisable(window) Source
Запрещает стандартное перетаскивание и выбор текста в указанном window. В качестве альтернативы предотвращению действия по умолчанию событий mousedown (см. #9), этот метод предотвращает нежелательные действия по умолчанию после mousedown. В поддерживаемых браузерах это означает захват событий dragstart и selectstart, предотвращение связанных с ними действий по умолчанию и немедленное прекращение их распространения. В браузерах, которые не поддерживают события выбора, свойство CSS user-select устанавливается в none для элемента документа. Этот метод предназначен для вызова при mousedown, за которым следует d3.dragEnable при mouseup.
d3.dragEnable(window[, noclick]) Source
Разрешает стандартное перетаскивание и выбор текста в указанном window; отменяет действие d3.dragDisable. Этот метод предназначен для вызова при mouseup, предшествующем d3.dragDisable при mousedown. Если noclick равно true, этот метод также временно подавляет события клика. Подавление событий клика истекает через таймаут в ноль миллисекунд, таким образом, оно подавляет только событие клика, которое непосредственно последует за текущим событием mouseup, если таковое имеется.
События перетаскивания
Когда вызывается обработчик события drag event listener, d3.event устанавливается в текущее событие перетаскивания. Объект event предоставляет несколько полей:
-
target— связанное поведение drag behavior. -
type— строка «start», «drag» или «end»; см. drag.on. -
subject— объект перетаскивания, определённый drag.subject. -
x— новая координата x объекта; см. drag.container. -
y— новая координата y объекта; см. drag.container. -
dx— изменение координаты x с момента предыдущего события перетаскивания. -
dy— изменение координаты y с момента предыдущего события перетаскивания. -
identifier— строка «mouse» или числовой идентификатор касания. -
active— количество активных жестов перетаскивания (при запуске и завершении, не включая текущий). -
sourceEvent— основное событие ввода, такое как mousemove или touchmove.
Поле event.active полезно для обнаружения первого события начала и последнего события завершения в последовательности одновременных жестов перетаскивания: оно равно нулю, когда начинается первый жест перетаскивания, и равно нулю, когда завершается последний жест перетаскивания.
Объект event также предоставляет метод event.on.
event.on(typenames, [listener]) Source
Аналогично drag.on, но применяется только к текущему жесту перетаскивания. Перед началом жеста перетаскивания создается копия текущих слушателей событий перетаскивания event listeners. Эта копия привязана к текущему жесту перетаскивания и изменяется методом event.on. Это полезно для временных слушателей, которые получают только события для текущего жеста перетаскивания. Например, этот слушатель события начала регистрирует временные слушатели событий перетаскивания и завершения как замыкания:
function started() {
var circle = d3.select(this).classed("dragging", true);
d3.event.on("drag", dragged).on("end", ended);
function dragged(d) {
circle.raise().attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
}
function ended() {
circle.classed("dragging", false);
}
}
© 2010–2018 Michael Bostock
Licensed under the BSD License.
https://github.com/d3/d3-drag