Spec-Zone.ru › D3.js 4

d3-drag

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

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

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

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.

END_OF_DOCUMENT_MARKER

Предмет жеста перетаскивания нельзя изменить после начала жеста. Доступ к предмету вызывается с тем же контекстом и аргументами, что и слушатели selection.on: текущие данные d и индекс i, с контекстом this в качестве текущего DOM-элемента. Во время оценки доступа к предмету d3.event — это событие перетаскивания перед началом drag. Используйте event.sourceEvent для доступа к событию начального ввода и event.identifier для доступа к идентификатору касания. event.x и event.y относительны к контейнеру и вычисляются с помощью d3.mouse или d3.touch, соответственно.

drag.clickDistance([distance]) Source

Если задано distance, устанавливает максимальное расстояние, на которое может перемещаться указатель мыши между событиями mousedown и mouseup, что приведет к последующему событию клика. Если в какой-либо момент между событиями mousedown и mouseup указатель мыши находится на расстоянии, равном или превышающем distance от своей позиции при mousedown, событие клика после mouseup будет подавлено. Если 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 — после того, как новый указатель станет активным (при mousedown или touchstart).
  • drag — после перемещения активного указателя (при mousemove или touchmove).
  • end — после того, как активный указатель станет неактивным (при mouseup, 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, d3.event устанавливается в текущее событие перетаскивания. Объект 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() {
  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–2017 Michael Bostock
Licensed under the BSD License.
https://github.com/d3/d3-drag

Spec-Zone.ru

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