Skip to content

控制流

¥Control flow

对于高级用法,转换提供了自定义控制流的方法。

¥For advanced usage, transitions provide methods for custom control flow.

生命过渡

¥The life of a transition

创建过渡后,例如通过 selection.transitiontransition.transition,你可以立即使用 transition.delaytransition.durationtransition.attrtransition.style 等方法配置过渡。指定目标值(例如 transition.attr)的方法会被求值同步;然而,需要插值起始值的方法(例如 transition.attrTweentransition.styleTween)必须推迟到转换开始时执行。

¥Immediately after creating a transition, such as by selection.transition or transition.transition, you may configure the transition using methods such as transition.delay, transition.duration, transition.attr and transition.style. Methods that specify target values (such as transition.attr) are evaluated synchronously; however, methods that require the starting value for interpolation, such as transition.attrTween and transition.styleTween, must be deferred until the transition starts.

创建后不久,无论是在当前帧的末尾还是在下一帧中,转换都会被安排。此时,延迟和 start 事件监听器可能无法再更改;尝试执行此操作会抛出错误,并显示“太晚了:已安排”(或者如果过渡已结束,则为“未找到过渡”)。

¥Shortly after creation, either at the end of the current frame or during the next frame, the transition is scheduled. At this point, the delay and start event listeners may no longer be changed; attempting to do so throws an error with the message “too late: already scheduled” (or if the transition has ended, “transition not found”).

当过渡效果随后启动时,它会中断同一元素上同名的激活过渡效果(如果有),并向已注册的监听器派发 interrupt 事件。(请注意,中断发生在启动时,而不是创建时,因此即使是零延迟过渡也不会立即中断活动过渡:旧过渡会获得最终帧。使用 selection.interrupt 可立即中断。)起始过渡还会取消在起始过渡之前创建的同一元素上所有同名的待处理过渡。然后,过渡会向已注册的监听器发送 start 事件。这是可以修改过渡效果的最后时刻:过渡的计时、补间和监听器在运行时不得更改;尝试执行此操作会抛出错误,并显示“太晚了:“已在运行”(或者,如果过渡已结束,则为“未找到过渡”)。过渡在启动后立即初始化其补间。

¥When the transition subsequently starts, it interrupts the active transition of the same name on the same element, if any, dispatching an interrupt event to registered listeners. (Note that interrupts happen on start, not creation, and thus even a zero-delay transition will not immediately interrupt the active transition: the old transition is given a final frame. Use selection.interrupt to interrupt immediately.) The starting transition also cancels any pending transitions of the same name on the same element that were created before the starting transition. The transition then dispatches a start event to registered listeners. This is the last moment at which the transition may be modified: the transition’s timing, tweens, and listeners may not be changed when it is running; attempting to do so throws an error with the message “too late: already running” (or if the transition has ended, “transition not found”). The transition initializes its tweens immediately after starting.

在帧期间,过渡开始,但在从此帧开始的所有过渡都已启动后,过渡才会首次调用其补间。批量执行补间初始化(通常涉及从 DOM 读取)可避免交叉 DOM 读写,从而提高性能。

¥During the frame the transition starts, but after all transitions starting this frame have been started, the transition invokes its tweens for the first time. Batching tween initialization, which typically involves reading from the DOM, improves performance by avoiding interleaved DOM reads and writes.

对于过渡处于活动状态的每一帧,它会调用其补间动画,eased t 值的范围是 0 到 1。在每一帧内,过渡效果都会按照注册的顺序调用其补间动画。

¥For each frame that a transition is active, it invokes its tweens with an eased t-value ranging from 0 to 1. Within each frame, the transition invokes its tweens in the order they were registered.

当过渡结束时,它将最后一次调用其补间动画,并将(非缓和的)t 值设置为 1。然后,它将 end 事件分派给已注册的监听器。这是可以检查过渡效果的最后时刻:结束后,过渡将从元素中删除,其配置将被销毁。(转换的配置也会在中断或取消时被销毁。)在转换被销毁后尝试检查转换会抛出错误,并显示“转换未找到”消息。

¥When a transition ends, it invokes its tweens a final time with a (non-eased) t-value of 1. It then dispatches an end event to registered listeners. This is the last moment at which the transition may be inspected: after ending, the transition is deleted from the element, and its configuration is destroyed. (A transition’s configuration is also destroyed on interrupt or cancel.) Attempting to inspect a transition after it is destroyed throws an error with the message “transition not found”.

selection.interrupt(name) {#selection_interrupt}

源代码 · 中断所选元素上指定名称的活动过渡,并取消任何具有指定名称的待处理过渡(如果有)。如果未指定名称,则使用 null。

¥Source · Interrupts the active transition of the specified name on the selected elements, and cancels any pending transitions with the specified name, if any. If a name is not specified, null is used.

中断元素上的过渡效果不会影响其后代元素上的任何过渡效果。例如,轴过渡 由轴 G 元素 的后代(刻度线、刻度标签、域路径等)上的多个独立、同步的转换组成。要中断轴的过渡,你必须中断其后代:

¥Interrupting a transition on an element has no effect on any transitions on any descendant elements. For example, an axis transition consists of multiple independent, synchronized transitions on the descendants of the axis G element (the tick lines, the tick labels, the domain path, etc.). To interrupt the axis transition, you must therefore interrupt the descendants:

js
selection.selectAll("*").interrupt();

通用选择器* 选择所有后代元素。如果你还想中断 G 元素本身:

¥The universal selector, *, selects all descendant elements. If you also want to interrupt the G element itself:

js
selection.interrupt().selectAll("*").interrupt();

interrupt(node, name)

源代码 · 中断指定节点上指定名称的活动过渡,并取消任何具有指定名称的待处理过渡(如果有)。如果未指定名称,则使用 null。另请参阅 selection.interrupt

¥Source · Interrupts the active transition of the specified name on the specified node, and cancels any pending transitions with the specified name, if any. If a name is not specified, null is used. See also selection.interrupt.

transition.end() {#transition_end}

源代码 · 返回一个承诺,当所有选定元素完成过渡时解析。如果任何元素的过渡被取消或中断,则 Promise 将被拒绝。

¥Source · Returns a promise that resolves when every selected element finishes transitioning. If any element’s transition is cancelled or interrupted, the promise rejects.

transition.on(typenames, listener) {#transition_on}

源代码 · 为每个选定元素添加或移除指定事件类型名的监听器。typenames 是以下字符串事件类型之一:

¥Source · Adds or removes a listener to each selected element for the specified event typenames. The typenames is one of the following string event types:

  • start - 当过渡开始时。

    ¥start - when the transition starts.

  • end - 当过渡结束时。

    ¥end - when the transition ends.

  • interrupt - 当过渡被中断时。

    ¥interrupt - when the transition is interrupted.

  • cancel - 当过渡被取消时。

    ¥cancel - when the transition is cancelled.

更多信息请参阅 过渡的生命周期。请注意,这些不是 selection.onselection.dispatch 实现的原生 DOM 事件,而是过渡事件!

¥See The Life of a Transition for more. Note that these are not native DOM events as implemented by selection.on and selection.dispatch, but transition events!

类型后面可以可选地跟一个句点 (.) 和一个名称;可选名称允许注册多个回调以接收相同类型的事件,例如 start.foostart.bar。要指定多个类型名称,请使用空格分隔类型名称,例如 interrupt endstart.foo start.bar

¥The type may be optionally followed by a period (.) and a name; the optional name allows multiple callbacks to be registered to receive events of the same type, such as start.foo and start.bar. To specify multiple typenames, separate typenames with spaces, such as interrupt end or start.foo start.bar.

当在选定节点上调度指定的过渡事件时,将为过渡元素调用指定的监听器,并传递当前数据 (d)、当前索引 (i) 和当前组(节点),并将其作为当前 DOM 元素。监听器始终看到其元素的最新数据,但索引是选择项的属性,在监听器分配时固定;要更新索引,请重新分配监听器。

¥When a specified transition event is dispatched on a selected node, the specified listener will be invoked for the transitioning element, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element. Listeners always see the latest datum for their element, but the index is a property of the selection and is fixed when the listener is assigned; to update the index, re-assign the listener.

如果先前已在选定元素上为相同类型名称注册了事件监听器,则在添加新监听器之前,会先移除旧监听器。要删除监听器,请将监听器设置为 null。要删除给定名称的所有监听器,请将 null 作为监听器传递,并将 .foo 作为类型名称传递,其中 foo 是名称;要移除所有没有名称的监听器,请指定 . 作为类型名称。

¥If an event listener was previously registered for the same typename on a selected element, the old listener is removed before the new listener is added. To remove a listener, pass null as the listener. To remove all listeners for a given name, pass null as the listener and .foo as the typename, where foo is the name; to remove all listeners with no name, specify . as the typename.

如果未指定监听器,则返回当前已分配的监听器,该监听器针对第一个(非空)选定元素(如果有)。如果指定了多个 typename,则返回第一个匹配的监听器。

¥If a listener is not specified, returns the currently-assigned listener for the specified event typename on the first (non-null) selected element, if any. If multiple typenames are specified, the first matching listener is returned.

transition.each(function) {#transition_each}

源代码 · 为每个选定元素调用指定函数,并传递当前数据 (d)、当前索引 (i) 和当前组 (nodes),this 作为当前 DOM 元素。此方法可用于为每个选定元素调用任意代码,并可用于创建上下文以同时访问父级和子级数据。等同于 selection.each

¥Source · Invokes the specified function for each selected element, passing in the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element. This method can be used to invoke arbitrary code for each selected element, and is useful for creating a context to access parent and child data simultaneously. Equivalent to selection.each.

transition.call(function, ...arguments) {#transition_call}

源代码 · 仅调用一次指定函数,并将此转换及其所有可选参数传入。返回此过渡效果。这相当于手动调用该函数,但有助于方法链式调用。例如,在可重用函数中设置多个属性:

¥Source · Invokes the specified function exactly once, passing in this transition along with any optional arguments. Returns this transition. This is equivalent to invoking the function by hand but facilitates method chaining. For example, to set several attributes in a reusable function:

js
function color(transition, fill, stroke) {
  transition
      .style("fill", fill)
      .style("stroke", stroke);
}

现在说:

¥Now say:

js
d3.selectAll("div").transition().call(color, "red", "blue");

这等同于:

¥This is equivalent to:

js
color(d3.selectAll("div").transition(), "red", "blue");

等同于 selection.call

¥Equivalent to selection.call.

transition.empty() {#transition_empty}

源代码 · 如果此转换不包含任何(非空)元素,则返回 true。等同于 selection.empty

¥Source · Returns true if this transition contains no (non-null) elements. Equivalent to selection.empty.

transition.nodes() {#transition_nodes}

源代码 · 返回此过渡集中所有(非空)元素的数组。等同于 selection.nodes

¥Source · Returns an array of all (non-null) elements in this transition. Equivalent to selection.nodes.

transition.node() {#transition_node}

源代码 · 返回此转换中的第一个(非空)元素。如果过渡为空,则返回 null。等同于 selection.node

¥Source · Returns the first (non-null) element in this transition. If the transition is empty, returns null. Equivalent to selection.node.

transition.size() {#transition_size}

源代码 · 返回此过渡中的元素总数。等同于 selection.size

¥Source · Returns the total number of elements in this transition. Equivalent to selection.size.