Переходы
Справочник API ▸ Основной модуль ▸ Переходы
Переход — это особый тип выбора, где операторы применяются плавно во времени, а не мгновенно. Переход выводится из выбора с помощью оператора переход. Хотя переходы обычно поддерживают те же операторы, что и выбор (например, attr и style), не все операторы поддерживаются; например, элементы необходимо добавлять до начала перехода. Оператор remove предназначен для удобного удаления элементов по завершении перехода.
Переходы могут иметь задержки и продолжительности для каждого элемента, вычисленные с помощью функций данных, аналогично другим операторам. Это упрощает ступенчатое выполнение перехода для разных элементов, как на основе данных, так и на основе индекса. Например, вы можете отсортировать элементы, а затем ступенчато выполнить переход для лучшего восприятия переупорядочивания элементов во время перехода. Более подробную информацию об этих методах см. в статье "Анимированные переходы в статистических графиках данных" от Heer & Robertson.
D3 имеет множество встроенных интерполяторов, которые упрощают переход произвольных значений. Например, вы можете перейти от строкового значения шрифта "500 12px sans-serif" к "300 42px sans-serif", и D3 найдёт числа, встроенные в строку, интерполируя размер и вес шрифта автоматически. Вы даже можете интерполировать произвольные вложенные объекты и массивы или данные SVG-путей. D3 позволяет создавать пользовательские интерполяторы, если встроенные недостаточно, используя операторы attrTween и styleTween. Интерполяторы D3 являются основой для масштабирования и могут использоваться вне переходов; интерполятор — это функция, которая отображает параметрическое значение t в области [0,1] на цвет, число или произвольное значение.
Несколько переходов могут выполняться на любом выборе последовательно или параллельно. Последовательные переходы на выборе включаются путем цепочки переходов с помощью transition.transition. Параллельные переходы на выборе включаются путем присвоения каждому параллельному переходу уникального имени. Только один переход с данным именем может быть активным на данном элементе в данный момент. Однако несколько переходов с тем же именем могут быть запланированы на одном и том же элементе; при условии, что они разделены во времени, каждый переход будет выполняться последовательно. Если новый переход выполняется на данном элементе, он неявно отменяет любые более старые переходы с тем же именем, включая те, которые были запланированы, но еще не выполнены. Это позволяет новым переходам, например, в ответ на новое пользовательское событие, заменять более старые переходы, даже если эти более старые переходы находятся в очереди или имеют задержки. Многоступенчатые переходы (переходы, которые создаются во время события "end" предыдущего перехода) считаются одного "возраста" с исходным переходом; внутренне это отслеживается с помощью монотонно возрастающих уникальных идентификаторов, которые наследуются при создании многоступенчатых переходов. Для прерывания активного перехода используйте selection.interrupt.
Дополнительную информацию о переходах см. в учебнике Работа с переходами.
Начало переходов
Переходы создаются с помощью d3.transition или selection.transition. Переходы начинаются автоматически при создании после задержки delay, которая по умолчанию равна нулю. Однако даже переход с нулевой задержкой запускается асинхронно, так как он ожидает один такт (~17 мс); задержка между созданием перехода и его первым тактом дает вам время на настройку перехода путем перезаписи параметров времени по умолчанию и регистрации сглаживаний.
Переходы имеют по умолчанию длительность duration 250 мс.
Если другой переход активен на данном элементе, новый переход с нулевой задержкой немедленно (синхронно) не прервет активный переход: старый переход не прерывается до тех пор, пока новый переход не начнётся на следующем такте, и старому переходу предоставляется заключительный такт. (В рамках такта активные переходы вызываются обратно в порядке их планирования.) Таким образом, старый переход может перезаписать значения атрибутов или стилей, которые были установлены синхронно при создании нового перехода. Используйте selection.interrupt, чтобы прервать любой активный переход и предотвратить получение им заключительного такта.
d3.transition([selection], [name])
Создать анимированный переход. Это эквивалентно d3.select(document).transition(). Этот метод используется редко, так как обычно проще получить переход из существующего выбора, чем выбор из существующего перехода. Если name указано, создать переход с указанным именем; в противном случае использовать пустое имя (“”).
При вызове с необязательным selection этот метод обычно возвращает указанный выбор; т.е. это действие без последствий. Однако в контексте transition.each этот метод создаст новый переход для указанного выбора, наследующий задержку, длительность и другие свойства родительского перехода. Это полезно для реализации переиспользуемых компонентов, которые могут вызываться как на выборах, так и на переходах, в последнем случае поддерживая вывод одновременных переходов. Примером этого является компонент оси D3.
transition.delay([delay])
Устанавливает задержку перехода в миллисекундах. Если delay — константа, то всем элементам задаётся одинаковая задержка; в противном случае, если delay — функция, то функция вычисляется для каждого элемента выбора (в порядке), получая текущую запись d и текущий индекс i, с контекстом this в качестве текущего DOM-элемента. Возвращаемое значение функции используется для установки задержки каждого элемента. По умолчанию задержка равна 0. Если delay не указан, возвращает задержку, привязанную к первому непустому элементу перехода.
Установка задержки, являющейся кратным индексу i, является удобным способом ступенчатого выполнения переходов для элементов. Например, если вы использовали фиксированную длительность duration и имеете n элементов в текущем выборе, вы можете ступенчато выполнить переход за 2 * duration, сказав:
.delay(function(d, i) { return i / n * duration; }) Вы также можете вычислить задержку как функцию данных, тем самым создав анимацию, управляемую данными.
Обратите внимание, что задержка всегда относительна к первому переходу в цепочке.
transition.duration([duration])
Указывает длительность перехода для каждого элемента в миллисекундах. Если duration — константа, то всем элементам задаётся одинаковая длительность; в противном случае, если duration — функция, то функция вычисляется для каждого элемента выбора (в порядке), получая текущую запись d и текущий индекс i, с контекстом this в качестве текущего DOM-элемента. Возвращаемое значение функции используется для установки длительности каждого элемента. По умолчанию длительность равна 250 мс. Если duration не указан, возвращает длительность, привязанную к первому непустому элементу перехода.
transition.ease([value[, arguments…]])
Указывает функцию сглаживания перехода easing function. Если value — функция, она используется для сглаживания текущего параметрического значения времени t, которое обычно находится в диапазоне [0,1]. (В конце перехода t может быть немного больше 1.) В противном случае value предполагается строковым, и все аргументы передаются d3.ease для генерации функции сглаживания. По умолчанию функция сглаживания равна "cubic-in-out". Обратите внимание, что настроить функцию сглаживания для каждого элемента или атрибута невозможно; однако, если вы используете функцию сглаживания "linear", вы можете применить пользовательское сглаживание внутри интерполятора, используя attrTween или styleTween. Если не указано никаких аргументов, возвращает функцию сглаживания, привязанную к первому непустому элементу перехода.
Работа с переходами
Содержимое
transition.attr(name, value)
Переход значения атрибута с указанным name к указанному value. Начальное значение перехода — текущее значение атрибута (убедитесь, что вы предварительно установили начальное значение, если не хотите неприятностей), а конечное значение — указанное value. Если value — константа, то все элементы переходят к одному и тому же значению атрибута; в противном случае, если value — функция, то функция вычисляется для каждого элемента выбора (в порядке), получая текущую запись d и текущий индекс i, с контекстом this в качестве текущего DOM-элемента. Возвращаемое значение функции используется для перехода атрибута каждого элемента. Значения null не поддерживаются, так как интерполятор был бы неопределён; если вы хотите удалить атрибут по завершении перехода, используйте remove.
Интерполятор выбирается автоматически на основе конечного значения. Если конечное значение — число, начальное значение приводится к числу и используется interpolateNumber. Если конечное значение — строка, выполняется проверка, представляет ли строка цвет в формате /^(#|rgb\(|hsl\()/, или один из именованных цветов CSS; если да, то начальное значение приводится к цветовому значению RGB и используется interpolateRgb. В противном случае используется interpolateString, который интерполирует числа, встроенные в строки.
transition.attrTween(name, tween)
Переход значения атрибута с указанным name в соответствии с указанной функцией tween. Начальное и конечное значение перехода определяется tween; функция tween вызывается при запуске перехода на каждом элементе, получая текущую запись d, текущий индекс i и текущее значение атрибута a, с контекстом this в качестве текущего DOM-элемента. Возвращаемое значение tween должно быть интерполятором: функцией, которая отображает параметрическое значение t в области [0,1] на цвет, число или произвольное значение.
Например, оператор attr построен поверх оператора attrTween. Функция сглаживания, используемая оператором attr, зависит от того, является ли конечное значение функцией или константой. Если конечное значение — функция:
function tween(d, i, a) {
return d3.interpolate(a, String(value.call(this, d, i)));
} В противном случае, если конечное значение — константа:
function tween(d, i, a) {
return d3.interpolate(a, String(value));
} Оператор attrTween используется, когда требуется пользовательский интерполятор, например, такой, который понимает семантику данных SVG-пути. Одним из распространённых методов является интерполяция пространства данных, где interpolateObject используется для интерполяции двух значений данных, а результат этой интерполяции затем используется (скажем, с формой) для вычисления нового значения атрибута. Используйте оператор attr для более простого общего случая, когда интерполятор может быть автоматически получен из текущего значения атрибута до желаемого конечного значения.
transition.style(name, value[, priority])
Переход значения свойства CSS-стиля с указанным name к указанному value. Также можно указать необязательный priority, либо как null, либо как строку "important" (без восклицательного знака). Начальное значение перехода — текущее вычисленное значение свойства стиля, а конечное значение — указанное value. Если value является константой, то все элементы переходят к одному значению свойства стиля; в противном случае, если value является функцией, то функция вычисляется для каждого выбранного элемента (в порядке), получая текущее значение данных d и текущий индекс i, с контекстом this как текущим элементом DOM. Возвращаемое значение функции затем используется для перехода свойства стиля каждого элемента. Значения null не поддерживаются, потому что интерполятор был бы неопределённым; если вы хотите удалить свойство стиля после завершения перехода, прослушивайте событие end.
Интерполятор выбирается автоматически на основе конечного значения. Если конечное значение является числом, начальное значение приводится к числу и используется interpolateNumber. Если конечное значение — строка, выполняется проверка, представляет ли строка цвет в формате /^(#|rgb\(|hsl\()/, или один из именованных цветов CSS; если да, начальное значение приводится к цвету RGB и используется interpolateRgb. В противном случае используется interpolateString, который интерполирует числа, вложенные в строки.
Обратите внимание, что вычисленное начальное значение может отличаться от ранее установленного значения, особенно если свойство стиля было установлено с помощью сокращённого свойства (например, стиль "font", который является сокращением для "font-size", "font-face" и т. д.). Кроме того, вычисленные размеры, такие как "font-size" и "line-height", всегда указаны в пикселях, поэтому необходимо указать конечное значение также в пикселях, если это уместно.
transition.styleTween(name, tween[, priority])
Переход значения свойства CSS-стиля с указанным name в соответствии с указанной функцией tween. Также можно указать необязательный priority, либо как null, либо как строку "important" (без восклицательного знака). Начальное и конечное значения перехода определяются функцией tween; функция tween вызывается при запуске перехода для каждого элемента, получая текущее значение данных d, текущий индекс i и текущее значение атрибута a, с контекстом this как текущим элементом DOM. Возвращаемое значение tween должно быть интерполятором: функцией, которая отображает параметрическое значение t в области [0,1] на цвет, число или произвольное значение.
Например, оператор style построен поверх оператора styleTween. Функция tween, используемая оператором style, зависит от того, является ли конечное значение функцией или константой. Если конечное значение является функцией:
function tween(d, i, a) {
return d3.interpolate(a, String(value.call(this, d, i)));
} В противном случае, если конечное значение является константой:
function tween(d, i, a) {
return d3.interpolate(a, String(value));
} Оператор styleTween используется, когда требуется пользовательский интерполятор, например, такой, который понимает семантику CSS3-преобразований. Используйте оператор style для более простого общего случая, где интерполятор может быть автоматически получен из текущего вычисленного значения свойства стиля до желаемого конечного значения.
transition.text(value)
Оператор text основан на свойстве textContent; установка текстового содержимого заменит любые существующие дочерние элементы.
Установите текстовое содержимое на указанное значение для всех выбранных элементов при запуске перехода. Если value является константой, то всем элементам задаётся одно и то же текстовое содержимое; в противном случае, если value является функцией, то функция вычисляется для каждого выбранного элемента (в порядке), получая текущее значение данных d и текущий индекс i, с контекстом this как текущим элементом DOM. Возвращаемое значение функции затем используется для установки текстового содержимого каждого элемента. Значение null очистит содержимое.
transition.tween(name, factory)
Регистрирует пользовательский tween для указанного name. При запуске перехода указанная функция factory вызывается для каждого выбранного элемента в переходе, получая данные элемента (d) и индекс (i) в качестве аргументов, с элементом как контекстом (this). Фабрика должна вернуть функцию tween, которая будет вызываться в течение перехода. Функция tween вызывается повторно, получая текущее нормированное время t в [0, 1]. Если фабрика возвращает null, tween не выполняется для выбранного элемента.
Метод tween используется внутренне для реализации attr и style tween, и может быть использован для интерполяции другого содержимого документа. Например, чтобы интерполировать текстовое содержимое от 0 до 100:
selection.transition().tween("text", function() {
var i = d3.interpolateRound(0, 100);
return function(t) {
this.textContent = i(t);
};
}); Tween часто пишутся с использованием замыканий для захвата состояния, созданного при запуске перехода. В примере выше, интерполятор i инициализируется при запуске перехода, и затем используется в течение всего перехода. (Хотя обратите внимание, что в примере выше начальное значение перехода жёстко закодировано как ноль, в то время как чаще начальное значение перехода основано на текущем состоянии в DOM).
transition.remove()
Удаляет выбранные элементы в конце перехода. Если для любого выбранного элемента запланирован более поздний переход, эти элементы не будут удалены; однако, событие "end" всё равно будет отправлено.
Подпереходы
Переходы могут быть получены из существующих переходов, аналогично подвыборкам. Подпереходы наследуют ускорение, продолжительность и задержку от родительского перехода.
transition.select(selector)
Для каждого элемента в текущем переходе выбирается первый дочерний элемент, который соответствует указанной строке selector. Если ни один элемент не соответствует указанному селектору для текущего элемента, элемент с текущим индексом будет равен null в возвращённой выборке; операторы (за исключением data) автоматически пропускают элементы null, тем самым сохраняя индекс существующей выборки. Если текущий элемент имеет связанные данные, эти данные наследуются возвращённой подвыборкой и автоматически привязываются к вновь выбранным элементам. Если несколько элементов соответствуют селектору, только первый соответствующий элемент в порядке обхода документа будет выбран.
Этот метод примерно эквивалентен:
selection.select(selector).transition()
где selection — основная выборка текущего перехода. Кроме того, возвращённый новый переход наследует ускорение, продолжительность и задержку от текущего перехода.
transition.selectAll(selector)
Для каждого элемента в текущем переходе выбираются дочерние элементы, которые соответствуют указанной строке selector. Возвращённая выборка группируется по родительскому узлу в текущей выборке. Если ни один элемент не соответствует указанному селектору для текущего элемента, группа с текущим индексом будет пустой в возвращённой выборке. Подвыборка не наследует данные от текущей выборки; однако, если данные были ранее привязаны к выбранным элементам, эти данные будут доступны для операторов.
Этот метод примерно эквивалентен:
selection.selectAll(selector).transition()
где selection — основная выборка текущего перехода. Кроме того, возвращённый новый переход наследует ускорение, продолжительность и задержку от текущего перехода. Продолжительность и задержка для каждого дочернего элемента наследуются от продолжительности и задержки родительского элемента в текущем переходе.
transition.filter(selector)
Фильтрует переход, возвращая новый переход, содержащий только элементы, для которых указанный selector имеет значение true. Selector может быть указан либо как функция, либо как строка селектора, такая как ".foo". Как и с другими операторами, функция получает текущее значение данных d и индекс i, с контекстом this как текущим элементом DOM. Подобно встроенному методу массива filter, возвращённая выборка не сохраняет индекс исходной выборки; она возвращает копию с удалёнными элементами. Если вы хотите сохранить индекс, используйте select вместо этого. Например, чтобы выбрать каждый второй элемент:
var odds = transition.select(function(d, i) { return i & 1 ? this : null; }); Аналогично, используя функцию фильтра:
var odds = transition.filter(function(d, i) { return i & 1; }); Или селектор фильтра:
var odds = transition.filter(":nth-child(odd)"); Таким образом, вы можете использовать либо select, либо filter, чтобы применить tween к подмножеству элементов.
transition.transition()
Создаёт новый переход на тех же выбранных элементах, который начинается, когда этот переход заканчивается. Новый переход наследует задержку, равную задержке этого перехода + продолжительность, чтобы контролировать этот временной интервал. Новый переход также наследует имя, продолжительность и ускорение этого перехода. Это можно использовать для определения цепочек переходов без необходимости прослушивания событий "end".
Как описано выше, состояние задержки цепочек переходов используется как подложка для цепочки. Это означает, что метод delay будет иметь неожиданное поведение в этом контексте, однако, если вы хотите добавить задержку между цепочками переходов, простой способ сделать это — вставить переход без действия:
selection.transition() // this transition runs from t=1s to t=3s
.delay(1000)
.duration(2000)
.transition() // then a delay from t=3s to t=4s
.duration(1000)
.transition() // then lastly another transition from t=4s to t=5s Хотя обратите внимание, что последний переход в этой цепочке наследует продолжительность 1s от промежуточной паузы, а не продолжительность 2s от первого перехода.
Управление
transition.each([type, ]listener)
Если type указан, добавляет обработчик для событий перехода, поддерживая события "start", "end" и "interrupt". Обработчик вызывается для каждого отдельного элемента в переходе.
Событие start вызывается во время первого асинхронного обратного вызова (тика) перехода, до вызова каких-либо анимаций. Для переходов с нулевой задержкой это обычно происходит примерно через 17 мс после планирования перехода. События состояния полезны для запуска мгновенных изменений каждого элемента, таких как изменение атрибутов, которые нельзя интерполировать.
Событие end вызывается во время последнего асинхронного обратного вызова (тика) после истечения времени перехода и задержки, после вызова всех анимаций с t=1. Обратите внимание, что если переход прерывается позднее запланированным переходом для данного элемента, событие end для этого элемента не будет отправлено; прерванные переходы не вызывают событий end. Например, transition.remove планирует удаление каждого элемента по окончании перехода, но если переход прерван, элемент не будет удален. События end могут использоваться как альтернатива transition.transition для создания цепных переходов, выбрав текущий элемент, this, и выведя новый переход; однако это может привести к дрейфу часов со временем, и поэтому предпочтительнее использовать transition.transition.
Событие interrupt вызывается, если активный переход прерывается другим переходом с тем же именем для того же элемента. Событие interrupt отправляется на прерванном переходе непосредственно перед событием start на прерывающем переходе. Обратите внимание, что если переход отменён до его начала (например, если позднее запланированный переход начинается до отложенного перехода), событие interrupt не отправляется.
Если тип не указан, поведение аналогично selection.each: немедленно вызывает указанную функцию для каждого элемента в текущем переходе, передавая текущие данные d и индекс i, с this контекстом текущего элемента DOM. Любые переходы, созданные в рамках transition.each, унаследуют параметры перехода от родительского перехода, включая id, задержку, длительность и ускорение. Таким образом, переходы, созданные в transition.each, не прерывают родительский переход, подобно подпереходам.
Метод transition.each можно использовать для цепочки переходов и применения совмещённого времени для набора переходов. Например:
d3.transition()
.duration(750)
.ease("linear")
.each(function() {
d3.selectAll(".foo").transition()
.style("opacity", 0)
.remove();
})
.transition()
.each(function() {
d3.selectAll(".bar").transition()
.style("opacity", 0)
.remove();
}); Используя d3.select(this) в transition.each, вы даже можете унаследовать ступенчатую задержку для набора выбранных элементов. Этот метод используется компонентом Оси для поддержки автоматических переходов.
См. также пример Выход, Обновление, Вход.
transition.call(функция[, аргументы…])
Вызывает указанную функцию один раз, передавая текущий переход вместе со всеми необязательными аргументами. Оператор call всегда возвращает текущий переход, независимо от возвращаемого значения указанной функции. Оператор call идентичен вызову функции вручную; но он упрощает использование цепочки методов. Например, предположим, что мы хотим установить несколько атрибутов одинаковым образом в нескольких местах. Поэтому мы берём код и оборачиваем его в повторно используемую функцию:
function foo(transition) {
transition
.attr("name1", "value1")
.attr("name2", "value2");
} Теперь мы можем сказать так:
foo(d3.selectAll("div").transition()) Или, что эквивалентно:
d3.selectAll("div").transition().call(foo); Во многих случаях можно вызвать одну и ту же функцию foo как для переходов, так и для выборок, из-за идентичных методов как для выборок, так и для переходов! this контекст вызываемой функции также является текущим переходом. Это немного избыточно с первым аргументом, что мы могли бы исправить в будущем.
transition.empty()
Возвращает true, если текущий переход пуст; переход пуст, если он не содержит элементов, отличных от null.
transition.node()
Возвращает первый элемент, не равный null, в текущем переходе. Если переход пуст, возвращает null.
transition.size()
Возвращает общее количество элементов в текущем переходе.
Ускорение
d3.ease(тип[, аргументы…])
Возвращает встроенную функцию ускорения указанного типа со всеми необязательными аргументами. Функция ускорения принимает текущее параметрическое значение времени t в области [0,1] и отображает его на другое значение в аналогичном диапазоне; она обычно используется для задания ускорения перехода ускорения. Поддерживаются следующие типы ускорения:
- linear - функция тождества, t.
- poly(k) - возводит t в указанную степень k (например, 3).
- quad - эквивалентно poly(2).
- cubic - эквивалентно poly(3).
- sin - применяет тригонометрическую функцию sin.
- exp - возводит 2 в степень, основанную на t.
- circle - четверть окружности.
- elastic(a, p) - моделирует упругую ленту; может немного выходить за пределы 0 и 1.
- back(s) - моделирует движение в заднюю часть парковочного места.
- bounce - моделирует отскок.
Эти встроенные типы могут быть расширены с помощью различных режимов:
- in - функция тождества.
- out - меняет направление ускорения на [1,0].
- in-out - копирует и отображает функцию ускорения из [0,.5] и [.5,1].
- out-in - копирует и отображает функцию ускорения из [1,.5] и [.5,0].
Функция ускорения по умолчанию - "cubic-in-out", которая обеспечивает подходящую анимацию с замедлением в начале и конце.
ease(t)
Принимая параметрическое время t, обычно в диапазоне [0,1], возвращает значение времени с учётом ускорения. Возвращаемое значение обычно также находится в диапазоне [0,1], но может немного выходить за эти пределы для некоторых функций ускорения, таких как "elastic".
Таймеры
D3 внутренне поддерживает эффективную очередь таймеров, так что тысячи таймеров могут обрабатываться параллельно с минимальными накладными расходами; кроме того, эта очередь таймеров гарантирует согласованное время анимации при одновременном или поэтапном планировании переходов. Если ваш браузер поддерживает это, очередь таймеров будет использовать requestAnimationFrame для плавной и эффективной анимации. Очередь таймеров также разумно использует setTimeout при большой задержке до следующего запланированного события.
d3.timer(функция[, задержка[, время]])
Запускает пользовательский таймер анимации, вызывая указанную функцию многократно, пока она не вернёт true. Отменить таймер после его запуска нельзя, поэтому убедитесь, что ваша функция таймера возвращает true при завершении! Функция получает время, прошедшее в миллисекундах с момента запуска таймера.
При необходимости может быть указана необязательная числовая задержка в миллисекундах, когда указанная функция должна вызываться только после задержки. Задержка относительна к указанному времени в миллисекундах с начала эпохи UNIX; если время не указано, оно по умолчанию равно Date.now.
Вы можете использовать задержку и время для указания относительных и абсолютных моментов времени, когда функция должна начать вызываться. Например, уведомление календаря может быть закодировано как:
d3.timer(notify, -4 * 1000 * 60 * 60, +new Date(2012, 09, 29)); // four hours before midnight October 29 (months are zero-based)
Обратите внимание, что если d3.timer вызывается внутри обратного вызова другого таймера, новый таймер будет вызван немедленно в конце текущего кадра (если активен, как определено заданной задержкой и временем), а не ждать следующего кадра.
d3.timer.flush()
Немедленно выполнить (вызвать один раз) все активные таймеры. Обычно переходы с нулевой задержкой выполняются после мгновенной задержки (<10 мс). Это может привести к кратковременной мерцанию, если браузер дважды отображает страницу: один раз в конце первого цикла событий, а затем сразу же при первом обратном вызове таймера. Выполняя очистку очереди таймеров в конце первого цикла событий, вы можете немедленно запустить все переходы с нулевой задержкой и избежать мерцания.
Интерполяция
D3 имеет много встроенных интерполяторов для упрощения переходов произвольных значений; интерполятор — это функция, которая отображает параметрическое значение t в области [0,1] в цвет, число или произвольное значение.
d3.interpolate(a, b)
Возвращает интерполятор по умолчанию между двумя значениями a и b. Тип интерполятора зависит от типа конечного значения b, используя следующий алгоритм:
- Если b — цвет, используется interpolateRgb.
- Если b — строка, используется interpolateString.
- Если b — массив, используется interpolateArray.
- Если b — объект и не может быть приведён к числу, используется interpolateObject.
- В противном случае используется interpolateNumber.
В зависимости от выбранного интерполятора, a приводится к соответствующему типу. Проверка цвета относится как к экземплярам d3.rgb, так и к другим цветовым пространствам, а также к строкам цветов вида /^(#|rgb\(|hsl\()/ или к именованным цветам CSS.
Поведение этого интерполятора по умолчанию может быть расширено для поддержки дополнительных типов путём добавления пользовательских интерполяторов в массив d3.interpolators.
interpolate(t)
Принимая параметр t, обычно в диапазоне [0,1], возвращает связанное значение интерполяции. Интерполяторы обычно используются совместно с масштабированием для отображения входного домена (например, количественной размерности) в выходной диапазон (например, диапазон цветов или позиций пикселей).
d3.interpolateNumber(a, b)
Возвращает числовой интерполятор между двумя числами a и b. Возвращаемый интерполятор эквивалентен:
function interpolate(t) {
return a * (1 - t) + b * t;
} Предупреждение: избегайте интерполяции к или из нуля, когда интерполятор используется для генерации строки (например, с помощью attr). Очень маленькие значения при преобразовании в строку могут быть преобразованы в научную запись и привести к временному недопустимому атрибуту или свойству стиля. Например, число 0.0000001 преобразуется в строку "1e-7". Это особенно заметно при интерполяции значений непрозрачности. Чтобы избежать научной записи, начните или закончите переход со значения 1e-6, которое является наименьшим значением, которое не преобразуется в экспоненциальную запись в строке.
d3.interpolateRound(a, b)
Возвращает числовой интерполятор между двумя числами a и b; интерполятор аналогичен interpolateNumber, за исключением того, что он округляет результирующее значение до ближайшего целого.
d3.interpolateString(a, b)
Возвращает строковый интерполятор между двумя строками a и b. Строковый интерполятор находит числа, вложенные в a и b, где каждое число имеет вид:
/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g
Для каждого числа, вставленного в b, интерполятор попытается найти соответствующее число в a. Если соответствующее число найдено, создаётся числовой интерполятор с использованием interpolateNumber. Остальные части строки b используются как шаблон: статические части строки b остаются неизменными для интерполяции, а интерполированные числовые значения встраиваются в шаблон. Например, если a равно "300 12px sans-serif", а b равно "500 36px Comic-Sans", находятся два вставленных числа. Остальные статические части строки — это пробел между двумя числами (" ") и суффикс ("px Comic-Sans"). Результат интерполятора при t = 0,5 — "400 24px Comic-Sans".
d3.interpolateRgb(a, b)
Возвращает интерполятор цветового пространства RGB между двумя цветами a и b. Цвета a и b не обязательно должны быть в формате RGB, но они будут преобразованы в RGB с помощью d3.rgb. Красная, зелёная и синяя составляющие интерполируются линейно аналогично interpolateRound, так как дробные значения компонентов не допускаются. Возвращаемое значение интерполятора — строка шестнадцатеричного представления RGB.
d3.interpolateHsl(a, b)
Возвращает интерполятор цветового пространства HSL между двумя цветами a и b. Цвета a и b не обязательно должны быть в формате HSL, но они будут преобразованы в HSL с помощью d3.hsl. Оттенок, насыщенность и светлость интерполируются линейно аналогично interpolateNumber. (Используется кратчайший путь между начальным и конечным оттенком.) Возвращаемое значение интерполятора — строка шестнадцатеричного представления RGB.
d3.interpolateLab(a, b)
Возвращает интерполятор цветового пространства L*a*b* между двумя цветами a и b. Цвета a и b будут преобразованы в L*a*\b*, если это необходимо, с помощью d3.lab. Затем цветовые компоненты интерполируются линейно аналогично interpolateNumber. Возвращаемое значение интерполятора — строка шестнадцатеричного представления RGB.
d3.interpolateHcl(a, b)
Возвращает интерполятор цветового пространства HCL между двумя цветами a и b. Цвета a и b будут преобразованы в HCL, если это необходимо, с помощью d3.hcl. Затем цветовые компоненты интерполируются линейно аналогично interpolateNumber. (Используется кратчайший путь между начальным и конечным оттенком.) Возвращаемое значение интерполятора — строка шестнадцатеричного представления RGB.
d3.interpolateArray(a, b)
Возвращает интерполятор массивов между двумя массивами a и b. Внутри создаётся шаблон массива, длина которого соответствует длине b. Для каждого элемента в b, если существует соответствующий элемент в a, создаётся универсальный интерполятор для двух элементов с помощью interpolate. Если такого элемента нет, используется статическое значение из b в шаблоне. Затем, для заданного параметра t, вычисляются встроенные интерполяторы шаблона. Обновлённый шаблон массива возвращается. Например, если a — массив [0, 1], а b — массив [1, 10, 100], то результат интерполятора при t = 0,5 — массив [.5, 5.5, 100].
Примечание: защитная копия массива-шаблона не создаётся; изменения возвращаемого массива могут негативно повлиять на последующее вычисление интерполятора. Копия не создаётся, так как интерполяторы должны быть быстрыми, поскольку они являются частью внутреннего цикла анимации.
d3.interpolateObject(a, b)
Возвращает интерполятор объектов между двумя объектами a и b. Внутри создаётся шаблон объекта, имеющий те же свойства, что и b. Для каждого свойства в b, если существует соответствующее свойство в a, создаётся универсальный интерполятор для двух элементов с помощью interpolate. Если такого свойства нет, статическое значение из b используется в шаблоне. Затем, для заданного параметра t, вычисляются встроенные интерполяторы шаблона, и обновлённый шаблон объекта возвращается. Например, если a — объект {x: 0, y: 1}, а b — объект {x: 1, y: 10, z: 100}, то результат интерполятора при t = 0,5 — объект {x: 0,5, y: 5,5, z: 100}.
Интерполяция объектов особенно полезна для интерполяции данных, где интерполируются данные, а не значения атрибутов. Например, вы можете интерполировать объект, описывающий дугу на круговой диаграмме, а затем использовать d3.svg.arc для вычисления новых данных пути SVG.
Примечание: защитная копия объекта-шаблона не создаётся; изменения возвращаемого объекта могут негативно повлиять на последующее вычисление интерполятора. Копия не создаётся, так как интерполяторы должны быть быстрыми, поскольку они являются частью внутреннего цикла анимации.
d3.interpolateTransform(a, b)
Возвращает интерполятор между двумя 2D аффинными преобразованиями, представленными a и b. Каждое преобразование разлагается на стандартное представление перемещения, поворота, наклона по оси x и масштабирования; эти компоненты преобразования затем интерполируются. Это поведение стандартизировано CSS: см. разложение матрицы для анимации.
d3.interpolateZoom(a, b)
Возвращает плавный интерполятор между двумя представлениями a и b двумерной плоскости, основанный на “плавном и эффективном масштабировании и перемещении” от Jarke J. van Wijk и Wim A.A. Nuij. Каждое представление определяется как массив из трёх чисел: cx, cy и width. Первые две координаты cx, cy представляют центр области просмотра; последняя координата width представляет размер области просмотра. Возвращаемый интерполятор также имеет свойство duration, которое кодирует рекомендуемую продолжительность перехода в миллисекундах. Эта продолжительность основана на длине пути по кривой траектории в пространстве x,y. Если вам нужен более медленный или быстрый переход, умножьте эту продолжительность на произвольный масштабный множитель (V, как описано в оригинальной статье).
d3.geo.interpolate(a, b)
См. d3.geo.interpolate.
d3.interpolators
Массив встроенных фабрик интерполяторов, используемых в d3.interpolate. Дополнительные фабрики интерполяторов могут быть добавлены в конец этого массива. Каждая фабрика может возвращать интерполятор, если она поддерживает интерполяцию двух заданных входных значений; в противном случае фабрика должна возвращать ложное значение, и будут опробованы другие интерполяторы.
Например, чтобы зарегистрировать пользовательский интерполятор, форматирующий доллары и центы, вы можете сказать:
d3.interpolators.push(function(a, b) {
var re = /^\$([0-9,.]+)$/, ma, mb, f = d3.format(",.02f");
if ((ma = re.exec(a)) && (mb = re.exec(b))) {
a = parseFloat(ma[1]);
b = parseFloat(mb[1]) - a;
return function(t) {
return "$" + f(a + b * t);
};
}
}); Затем d3.interpolate("$20", "$10")(1/3) возвращает $16.67.
© 2010–2016 Michael Bostock
Licensed under the BSD License.
https://github.com/d3/d3-3.x-api-reference/blob/master/Transitions.md