Я хочу создать временную шкалу, в которой пользователь может выбирать между прокруткой для увеличения или выбором области для увеличения. Есть некоторые примеры первых, как: https://bl.ocks.org/mbostock/4015254 Или наезд на области с кистью: https://bl.ocks.org/mbostock/f48fcdb929a620ed97877e4678ab15e6
Но я не могу найти пример, который делает оба. Как я могу сделать то и другое? Или есть примеры, которые я пропустил?Сдвижная и масштабируемая временная шкала с d3
ответ
Это не самая простая вещь для реализации. Как вы заметите, масштабирование на основе кисти не зависит от d3.zoom
, но вместо этого выполняет масштабирование через слушатели, которые запускают события, чтобы делать все необходимое для масштабирования осей и соответственно перемещать элементы сюжета.
Для сравнения, все прокрутка на основе примеры масштабирования обычно полагаются на d3.zoom
, который использует d3.zoom()
поведения, которое отслеживает все преобразования выполняются на участке в то время как панорамирование/масштабирование и несет полную ответственность за обновление различных элементов диаграммы. Трудность заключается в том, что два подхода отличаются друг от друга, и если вы вручную измените вид диаграммы с помощью чистки, вам нужно выяснить способ обновления внутреннего преобразования масштабирования, который ссылается на d3.zoom
, чтобы он знал об изменениях, сделанных с помощью события масштабирования на основе кисти.
Это совсем не легко сделать, потому что d3.zoom
не был предназначен для подачи информации из других источников, а внутренняя запись преобразований, которые были выполнены, не должна быть обновляемой/изменяемой. Вы можете обновить преобразование с помощью selection.call(zoom.transform, d3.zoomIdentity);
, но, к сожалению, он также запускает целую кучу событий, связанных с фактическим поведением масштабирования, чего вы не хотите, так как уже обработали все операции масштабирования с помощью масштабирования на основе кисти. Некрасиво, но эффективный обходной путь, что я был в состоянии использовать, чтобы сбросить масштаб преобразования был мутировать фактическое .__zoom
поля узла DOM, который привязан к d3.zoom
поведению следующим образом:
// WARNING: Ugly mutation of __zoom property of pan/scroll-zoom rect to
// reset the transform without having to fire events associated with zoom
// d3.select(".zoom").node().__zoom = {k: 1, x: 0, y: 0}; <-- Fails since __zoom contains other hidden objects
scrollZoom.node().__zoom["k"] = 1;
scrollZoom.node().__zoom["x"] = 0;
scrollZoom.node().__zoom["y"] = 0;
Так, например: Если вам нужна двумерная кисть для масштабирования прямоугольника, но также и d3.zoom
масштабирование для панорамирования и прокрутки мыши, тогда в любое время, когда вы будете использовать двумерную кисть для масштабирования, вам нужно сбросить преобразование d3.zoom обратно в преобразование идентичности, как указано выше. Это предотвращает и уродливое и резкое дрожание в реакции панорамирования/прокрутки при соединении 2D-кистей с масштабированием действий с помощью действий панорамирования/мыши с помощью преобразования в записи с d3.zoom
, не находящимся в синхронизации с представлением на дисплее (из-за двумерной кисти основанный на масштабировании, изменяющий представление без знания d3.zoom).
Вот что-то еще, что важно отметить:
d3.zoom
имеет ограничение в том, что в настоящее время он поддерживает только общий масштаб увеличения для обеих осей Х и Y (Source). Это, к сожалению, означает, что нет возможности сопоставить масштабирование с двухмерной кистью с использованием метода, основанного на d3.zoom
, поскольку масштабирование с использованием кисти с двумя кистями дает различное масштабирование масштабирования в X и Y. Если вы хотите делать что-то с минимальными проблемами, используя последовательный подход , Я бы рекомендовал посмотреть на использование d3.xyzoom. Это вилка d3.zoom
, которая реализует поддержку различных шкал для осей X и Y. Это позволит вам рассчитать соответствующие значения масштабирования и трансляции масштабирования X и Y для любого выбора кисти 2D, который затем можно будет подать в d3.zoom
, что позволит вам выполнить все масштабирование с использованием общего подхода (что также приводит к наименьшей сумме дублирования кода).
Если вы заинтересованы только в масштабировании с 1-му кистью, вы должны иметь возможность сопоставить это с d3.чтобы вам не приходилось иметь дело с двумя разными путями для обработки вида и масштабирования всех осей и других графических элементов в вашей диаграмме. Вот хороший пример этого:
https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172
Извиняюсь за длину этого поста, и если это немного бессвязное. Я работаю над тем, чтобы собрать блок на моей работе через пару дней, и я попытаюсь вернуться сюда и опубликовать ссылку, когда я это сделаю. Я только начал изучать D3 неделю назад, поэтому я учусь по пути.
Помог ли мой комментарий ниже? – HamsterHuey
Нет, я не смог его реализовать. Но в данный момент я сосредотачиваюсь на своих экзаменах, поэтому у меня нет времени потратить на него больше 1 дня. –