Spec-Zone.ru › D3.js 7

d3-drag

Перетаскивание — популярный и простой в освоении способ взаимодействия: переместите указатель на объект, нажмите и удерживайте, чтобы взять его, «перетащите» объект в новое место и отпустите, чтобы «опустить». Поведение перетаскивания D3 предоставляет удобную, но гибкую абстракцию для включения взаимодействия перетаскивания на выборки. Например, вы можете использовать d3-drag для облегчения взаимодействия с силовым графиком или симуляцией столкновения окружностей:

Force-Directed GraphForce Dragging II

Вы также можете использовать d3-drag для реализации пользовательских элементов интерфейса, таких как ползунок. Но поведение перетаскивания не ограничивается перемещением элементов; существует множество способов реагировать на жесты перетаскивания. Например, вы можете использовать его для выделения элементов на диаграмме рассеяния или для рисования линий на холсте:

Line Drawing

Поведение перетаскивания можно комбинировать с другими действиями, такими как d3-zoom для масштабирования.

Drag & Zoom II

Поведение перетаскивания не зависит от DOM, поэтому его можно использовать с SVG, HTML или даже Canvas! И вы можете расширить его с помощью продвинутых методов выбора, таких как наложение Вороного или поиск ближайшей цели:

Circle Dragging IVCircle Dragging II

Главное, поведение перетаскивания автоматически объединяет ввод мыши и сенсорного экрана и избегает особенностей браузеров. Когда события указателей станут более распространёнными, поведение перетаскивания будет поддерживать их тоже.

Установка

Если вы используете npm, npm install d3-drag. Также можно скачать последнюю версию с GitHub. Для обычного HTML в современных браузерах импортируйте d3-drag из Skypack:

<script type="module">

import {drag} from "https://cdn.skypack.dev/d3-drag@3";

const handler = drag();

</script>

Для устаревших сред можно загрузить UMD-пакет d3-drag с CDN на основе npm, например, jsDelivr; экспортируется глобальная переменная d3:

<script src="https://cdn.jsdelivr.net/npm/d3-dispatch@3"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-selection@3"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-drag@3"></script>
<script>

const handler = d3.drag();

</script>

Попробуйте d3-drag в вашем браузере.

Справочник по API

В этой таблице описано, как поведение перетаскивания интерпретирует события:

Событие Элемент прослушивания Событие перетаскивания Предотвращено значение по умолчанию?
mousedown⁵ выборка начало нет¹
mousemove² окно¹ перетаскивание да
mouseup² окно¹ конец да
dragstart² окно - да
selectstart² окно - да
click³ окно - да
touchstart выборка начало нет⁴
touchmove выборка перетаскивание да
touchend выборка конец нет⁴
touchcancel выборка конец нет⁴

Распространение всех обработанных событий немедленно останавливается. Если вы хотите предотвратить некоторые события, запускающие жест перетаскивания, используйте перетаскивание.filter.

¹ Необходимо для захвата событий за пределами iframe; см. #9.
² Применяется только во время активного жеста перетаскивания с помощью мыши; см. #9.
³ Применяется только сразу после некоторых жестов с использованием мыши; см. перетаскивание.clickDistance.
⁴ Необходимо для поддержки эмуляции клика на вводе сенсорного экрана; см. #9.
⁵ Игнорируется, если в течение 500 мс завершается жест сенсорного экрана; предполагается эмуляция клика.

d3.drag() · Исходный код, Примеры

Создает новое поведение перетаскивания. Возвращаемое поведение, перетаскивание, является как объектом, так и функцией и обычно применяется к выбранным элементам с помощью выборка.call.

drag(выборка) · Исходный код, Примеры

Применяет это поведение перетаскивания к указанной выборке. Эта функция обычно не вызывается напрямую и вместо этого вызывается через выборка.call. Например, чтобы создать поведение перетаскивания и применить его к выборке:

d3.selectAll(".node").call(d3.drag().on("start", started));

Внутренне поведение перетаскивания использует выборка.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-элементов, так как эти элементы обычно позиционируются относительно родителя. Однако при перетаскивании графических элементов с помощью холста вы можете переопределить контейнер как сам начальный элемент:

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), который получил начальное событие ввода; если эти данные не определены, создаётся объект, представляющий координаты указателя. При перетаскивании элементов окружности в SVG по умолчанию субъектом являются данные перетаскиваемой окружности. С холстом по умолчанию субъектом является данные элемента холста (независимо от того, где на холсте вы щелкнули). В этом случае более подходящим будет пользовательский аксессор субъекта, например, такой, который выбирает ближайшую окружность к мыши в заданном радиусе поиска:

function subject(event) {
  let 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.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, что также позволяет регистрировать временные обработчики событий для текущего жеста перетаскивания. Отдельные события отправляются для каждого активного указателя во время жеста перетаскивания. Например, если одновременно перетаскиваются несколько объектов с помощью нескольких пальцев, событие начала отправляется для каждого пальца, даже если оба пальца касаются одновременно. См. События перетаскивания для получения дополнительной информации.

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, если таковое имеется.

События перетаскивания

Когда вызывается обработчик событий перетаскивания, он получает текущее событие перетаскивания в качестве первого аргумента. Объект 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 полезно для обнаружения первого события начала и последнего события окончания в последовательности одновременных жестов перетаскивания: оно равно нулю, когда начинается первый жест перетаскивания и когда заканчивается последний.

Объект event также предоставляет метод event.on.

event.on(typenames, [listener]) · Source

Эквивалентно drag.on, но применяется только к текущему жесту перетаскивания. Перед началом жеста перетаскивания создаётся копия текущих обработчиков событий перетаскивания. Эта копия привязывается к текущему жесту перетаскивания и изменяется методом event.on. Это полезно для временных слушателей, которые получают события только для текущего жеста перетаскивания. Например, этот слушатель события начала регистрирует временные слушатели событий перетаскивания и окончания как замыкания:

function started(event) {
  const 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–2023 Michael Bostock
Licensed under the BSD License.
https://github.com/d3/d3-drag

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API