d3-drag
Перетаскивание — популярный и простой в освоении жест указателя: переместите указатель на объект, нажмите и удерживайте, чтобы взять его, «перетащите» объект в новое местоположение и отпустите, чтобы «опустить». Поведение перетаскивания D3 предоставляет удобную, но гибкую абстракцию для включения взаимодействия перетаскивания на выборках. Например, вы можете использовать d3-drag для облегчения взаимодействия с силовой направленной диаграммой или симуляцией сталкивающихся кругов:
Вы также можете использовать d3-drag для реализации пользовательских элементов интерфейса, таких как ползунок. Но поведение перетаскивания не только для перемещения элементов; есть множество способов реагировать на жест перетаскивания. Например, вы можете использовать его для выделения элементов в точечном графике или для рисования линий на холсте:
Поведение перетаскивания можно комбинировать с другими действиями, такими как d3-zoom для масштабирования.
Поведение перетаскивания не зависит от DOM, поэтому вы можете использовать его с SVG, HTML или даже Canvas! И вы можете расширить его с помощью сложных техник выбора, таких как наложение Вороного или поиск ближайшего целевого объекта:
Лучше всего, поведение перетаскивания автоматически объединяет ввод мыши и сенсорного ввода и избегает особенностей браузера. Когда события указателя будут более распространены, поведение перетаскивания также будет поддерживать их.
Установка
Если вы используете NPM, npm install d3-drag. В противном случае загрузите последнюю версию. Вы также можете загрузить напрямую с d3js.org, либо как автономную библиотеку, либо как часть D3. Поддерживаются среды AMD, CommonJS и vanilla. В vanilla экспортируется глобальная переменная d3:
<script src="https://d3js.org/d3-dispatch.v2.min.js"></script> <script src="https://d3js.org/d3-selection.v2.min.js"></script> <script src="https://d3js.org/d3-drag.v2.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.pointer для определения локальных координат указателя.
Контейнер-аксессор по умолчанию возвращает родительский узел элемента в исходной выборке (см. drag), который получил событие ввода. Это часто уместно при перетаскивании элементов SVG или HTML, поскольку эти элементы обычно позиционируются относительно родителя. Однако при перетаскивании графических элементов с помощью Canvas вы можете переопределить контейнер как сам начальный элемент:
function container() {
return this;
} В качестве альтернативы контейнер может быть указан непосредственно как элемент, например, drag.container(canvas).
drag.filter([filter]) · Источник, Примеры
Если filter указан, устанавливает фильтр событий в указанную функцию и возвращает поведение перетаскивания. Если filter не указан, возвращает текущий фильтр, который по умолчанию:
function filter(event) {
return !event.ctrlKey && !event.button;
} Если фильтр возвращает ложь, событие инициализации игнорируется, и никакие жесты перетаскивания не начинаются. Таким образом, фильтр определяет, какие события ввода игнорируются; по умолчанию фильтр игнорирует события mousedown на вторичных кнопках, поскольку эти кнопки обычно предназначены для других целей, таких как контекстное меню.
drag.touchable([touchable]) · Источник, Примеры
Если touchable указан, устанавливает детектор поддержки сенсорного ввода в указанную функцию и возвращает поведение перетаскивания. Если touchable не указан, возвращает текущий детектор поддержки сенсорного ввода, который по умолчанию:
function touchable() {
return navigator.maxTouchPoints || ("ontouchstart" in this);
} Обработчики событий сенсорного ввода регистрируются только в том случае, если детектор возвращает истину для соответствующего элемента, когда поведение перетаскивания применено. Детектор по умолчанию хорошо работает для большинства браузеров, которые способны к сенсорному вводу, но не для всех; например, эмулятор мобильного устройства Chrome не распознаёт.
drag.subject([subject]) · Источник, Примеры
Если subject указан, устанавливает аксессор объекта или функции и возвращает поведение перетаскивания. Если subject не указан, возвращает текущий аксессор объекта, который по умолчанию:
function subject(event, d) {
return d == null ? {x: event.x, y: event.y} : d;
} Предмет жеста перетаскивания представляет собой то, что перетаскивается. Он вычисляется при получении события инициализации, например, mousedown или touchstart, непосредственно перед началом жеста перетаскивания. Предмет затем отображается как event.subject в последующих событиях перетаскивания для этого жеста.
Предмет по умолчанию — это данные элемента в исходной выборке (см. drag), который получил событие ввода; если эти данные undefined, создается объект, представляющий координаты указателя. При перетаскивании кругов в SVG предмет по умолчанию — это данные перетаскиваемого круга. С Canvas предмет по умолчанию — это данные элемента холста (независимо от того, где на холсте вы щелкаете). В этом случае более подходящим будет пользовательский аксессор предмета, например, который выбирает ближайший круг к мыши в данном поиске radius:
function subject(event) {
var n = circles.length,
i,
dx,
dy,
d2,
s2 = radius * radius,
circle,
subject;
for (i = 0; i < n; ++i) {
circle = circles[i];
dx = event.x - circle.x;
dy = event.y - circle.y;
d2 = dx * dx + dy * dy;
if (d2 < s2) subject = circle, s2 = d2;
}
return subject;
} (При необходимости это можно ускорить, используя quadtree.find, simulation.find или delaunay.find.)
Возвращаемый предмет должен быть объектом, который предоставляет x и y свойства, чтобы относительное положение предмета и указателя сохранялось во время жеста перетаскивания. Если предмет равен null или undefined, жест перетаскивания для этого указателя не начинается; однако другие начальные касания могут начать жесты перетаскивания. См. также drag.filter.
Изменение объекта перетаскивания после начала жеста невозможно. Доступ к объекту вызывается с тем же контекстом и аргументами, что и слушатели selection.on: текущее событие (event) и данные d, с контекстом this в качестве текущего DOM-элемента. Во время вычисления аксессора объекта event представляет собой событие перетаскивания перед началом drag event. Используйте event.sourceEvent для доступа к исходному событию ввода и event.identifier для доступа к идентификатору касания. event.x и event.y относительны к контейнеру и вычисляются с помощью d3.pointer.
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: текущее событие (event) и данные d, с контекстом 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, которое также позволяет регистрировать временные обработчики событий для текущего жеста перетаскивания. Отдельные события отправляются для каждого активного указателя во время жеста перетаскивания. Например, если одновременно перетаскиваются несколько объектов с несколькими пальцами, событие start отправляется для каждого пальца, даже если оба пальца коснулись одновременно. См. События перетаскивания для получения дополнительной информации.
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 он получает текущее событие перетаскивания в качестве первого аргумента. Объект event предоставляет несколько полей:
-
target— связанное поведение перетаскивания. -
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 полезно для определения первого события start и последнего события end в последовательности одновременных жестов перетаскивания: оно равно нулю, когда начинается первый жест перетаскивания, и равно нулю, когда завершается последний жест перетаскивания.
Объект event также предоставляет метод event.on.
event.on(typenames, [listener]) · Source
Эквивалентно drag.on, но применяется только к текущему жесту перетаскивания. Перед началом жеста перетаскивания создается копия текущих обработчиков событий перетаскивания . Эта копия привязана к текущему жесту перетаскивания и изменяется с помощью event.on. Это полезно для временных обработчиков, которые получают события только для текущего жеста перетаскивания. Например, этот обработчик события start регистрирует временные обработчики событий drag и end как замыкания:
function started(event) {
var circle = d3.select(this).classed("dragging", true);
event.on("drag", dragged).on("end", ended);
function dragged(event, d) {
circle.raise().attr("cx", d.x = event.x).attr("cy", d.y = event.y);
}
function ended() {
circle.classed("dragging", false);
}
}
© 2010–2020 Michael Bostock
Licensed under the BSD License.
https://github.com/d3/d3-drag