控制流
对于高级用法,过渡提供了自定义控制流的方法。
过渡的生命周期
在创建过渡后立即,例如通过 selection.transition 或 transition.transition,您可以使用诸如 transition.delay、transition.duration、transition.attr 和 transition.style 之类的方法配置过渡。指定目标值的方法(例如 transition.attr)是同步评估的;但是,需要起始值进行插值的方法,例如 transition.attrTween 和 transition.styleTween,必须延迟到过渡开始时才执行。
在创建后不久,在当前帧结束或下一帧期间,过渡将被调度。此时,延迟和 start
事件监听器将无法再更改;尝试这样做会抛出带有消息“太迟:已调度”的错误(或者如果过渡已结束,则为“未找到过渡”)。
当过渡随后开始时,它会中断同一元素上具有相同名称的活动过渡(如果有),并向注册的监听器分派一个 interrupt
事件。(请注意,中断发生在开始时,而不是创建时,因此即使是零延迟过渡也不会立即中断活动过渡:旧的过渡将得到最后一帧。使用 selection.interrupt 立即中断。)起始过渡还会取消之前创建的同一元素上具有相同名称的所有待处理过渡。然后,过渡向注册的监听器分派一个 start
事件。这是最后可以修改过渡的时间:过渡的时间安排、补间和监听器在它运行时无法更改;尝试这样做会抛出带有消息“太迟:正在运行”的错误(或者如果过渡已结束,则为“未找到过渡”)。过渡在开始后立即初始化其补间。
在过渡开始的帧中,但在所有在本帧开始的过渡都已开始之后,过渡会首次调用其补间。通过批处理补间初始化(通常涉及从 DOM 读取),通过避免交错的 DOM 读取和写入来提高性能。
对于过渡处于活动状态的每一帧,它都会使用 缓动 的 t 值(范围从 0 到 1)调用其补间。在每一帧内,过渡按注册的顺序调用其补间。
当过渡结束时,它会使用(未缓动的)t 值 1 最终一次调用其补间。然后,它向注册的监听器分派一个 end
事件。这是最后可以检查过渡的时间:结束之后,过渡将从元素中删除,并且其配置将被销毁。(过渡的配置也会在中断或取消时被销毁。)尝试在过渡被销毁后检查过渡会抛出带有消息“未找到过渡”的错误。
selection.interrupt(name)
来源 · 中断选定元素上指定 name 的活动过渡,并取消所有待处理的 name 过渡(如果有)。如果未指定名称,则使用 null。
中断元素上的过渡不会影响任何后代元素上的任何过渡。例如,轴过渡 由轴 G 元素(刻度线、刻度标签、域路径等)后代上的多个独立的同步过渡组成。因此,要中断轴过渡,您必须中断后代
selection.selectAll("*").interrupt();
通用选择器,*
,选择所有后代元素。如果您还想中断 G 元素本身
selection.interrupt().selectAll("*").interrupt();
interrupt(node, name)
来源 · 中断指定 node 上指定 name 的活动过渡,并取消所有待处理的 name 过渡(如果有)。如果未指定名称,则使用 null。另请参阅 selection.interrupt。
transition.end()
来源 · 返回一个承诺,该承诺在所有选定元素完成过渡时解析。如果任何元素的过渡被取消或中断,则承诺将被拒绝。
transition.on(typenames, listener)
来源 · 为选定元素的指定事件 typenames 添加或删除 listener。typenames 是以下字符串事件类型之一
start
- 当过渡开始时。end
- 当过渡结束时。interrupt
- 当过渡被中断时。cancel
- 当过渡被取消时。
有关更多信息,请参阅 过渡的生命周期。请注意,这些不是由 selection.on 和 selection.dispatch 实现的本机 DOM 事件,而是过渡事件!
类型后面可以可选地加上一个句点 (.
) 和一个名称;可选名称允许注册多个回调以接收相同类型的事件,例如 start.foo
和 start.bar
。要指定多个类型名,请用空格分隔类型名,例如 interrupt end
或 start.foo start.bar
。
当选定节点上分派指定的过渡事件时,将为过渡元素调用指定的 listener,并传递当前数据 (d)、当前索引 (i) 和当前组 (nodes),其中 this 为当前 DOM 元素。监听器始终看到其元素的最新数据,但索引是选择的属性,并在分配监听器时固定;要更新索引,请重新分配监听器。
如果之前在选定元素上为同一个 typename 注册了事件监听器,则在添加新的监听器之前会删除旧的监听器。要删除监听器,请将 null 作为 listener 传递。要删除给定名称的所有监听器,请将 null 作为 listener 传递,并将 .foo
作为 typename 传递,其中 foo
为名称;要删除所有没有名称的监听器,请将 .
作为 typename 指定。
如果未指定 listener,则返回为指定事件 typename 分配给第一个(非 null)选定元素(如果有)的当前监听器。如果指定了多个类型名,则返回第一个匹配的监听器。
transition.each(function)
来源 · 为每个选定元素调用指定的 function,并传递当前数据 (d)、当前索引 (i) 和当前组 (nodes),其中 this 为当前 DOM 元素。此方法可用于为每个选定元素调用任意代码,对于创建访问父级和子级数据的上下文很有用。等效于 selection.each。
transition.call(function, ...arguments)
源代码 · 仅执行一次指定的函数,并将此过渡以及任何可选的参数传递给它。返回此过渡。这相当于手动调用函数,但它有助于方法链接。例如,要在可重用的函数中设置多个属性
function color(transition, fill, stroke) {
transition
.style("fill", fill)
.style("stroke", stroke);
}
现在假设
d3.selectAll("div").transition().call(color, "red", "blue");
这等同于
color(d3.selectAll("div").transition(), "red", "blue");
等同于 选择.call.
过渡.empty()
源代码 · 如果此过渡不包含任何(非空)元素,则返回 true。等同于 选择.empty.
过渡.nodes()
源代码 · 返回此过渡中所有(非空)元素的数组。等同于 选择.nodes.
过渡.node()
源代码 · 返回此过渡中的第一个(非空)元素。如果过渡为空,则返回 null。等同于 选择.node.