D3中动画(transition函数)的使用

关于transition的几个基本点:

1. transition()是针对与每个DOM element的,每个DOM element的transition并不会影响其他DOM element的transition操作;

2. 对于每一个DOM element的transition每次只能执行一个,如果在一个DOM element上添加了许多transition操作,只有最后一个会起作用,前面的都会被覆盖掉。但是例外是,当这些transition是chaining的形式连接的时候,这些transition会按照先后顺序依次执行(大致形式就是:.....transition()....transition()....)。具体可以查看这个例子:http://bl.ocks.org/mbostock/3943967

3. 在对每个transition动作除了用duration()函数指定持续时间之外,也可以通过delay()函数来对transition动作加一定时间的时间延迟,2中提到的例子有相关的代码。

4. transition比较核心的一点就是,必须要有两个核心的frame:起始frame是怎么样,终止frame是什么样。这些都要在schedule一个transition动作的时候指定好。因此有些操作就没法加transition,例如,创建一个新的DOM element,因为没有起始frame.

5. 并不是所有的属性都能加transition,目前D3支持四种数据/属性的transition:

  • numbers
  • colors
  • geometric transforms
  • strings with embedded numbers (e.g., "96px") (注意,这是目前能够应用transition的几种属性)

因此,如果要多一个文本的创建加transition就是不可能的。

6. Transition 和join操作相结合的一个常用的模板:

var bar = svg.selectAll(".bar")
    .data(data, function(d) { return d.key; });

bar.enter().append("rect")
    .attr("class", "bar")
    … // initialize entering bars

bar.transition()
    … // transition entering + updating bars

bar.exit().transition()
    … // transition exiting bars
    .remove();

主要参考文章:working with transitions: http://bost.ocks.org/mike/transition/

以下是Mike Bostock的博客原文:

Working with Transitions

D3’s selection.transition method makes it easy to animate transitions when changing the DOM. For example, to change the text color to red instantaneously, you can select the body element and set the color style:

d3.select("body").style("color", "red");

To instead animate the change over time, derive a transition:

d3.select("body").transition().style("color", "red");

This ease-of-use comes from D3’s transition interface mirroring the selection interface: nearly everything you can do to a selection of elements, you can also do to a transition, causing the change to be animated over time rather than instantaneous.

Yet looks can be deceiving because selections and transitions are not perfectly equivalent: transitions provide only a subset of selection functionality. These nuances are due to the long-running, asynchronous nature of transitions. Before you attempt more complicated uses of transitions, it is helpful to understand the system’s underlying design.

Note: This article discusses transitions as implemented in version 3.0, which was released in December 2012. You can download D3 3.0 from d3js.org or GitHub.

#Transitions Are a Form of Animation

For more general uses, consider implementing animations withd3.timer rather than as transitions.

Transitions are a limited form of key frame animation with only two key frames: start and end. The starting key frame is typically the current state of the DOM, and the ending key frame is a set of attributes, styles and other properties you specify. Transitions are thus well-suited for transitioning to a new view without complicated code that depends on the starting view.

Look again at this example transition:

d3.select("body").transition().style("color", "red");

Although only a single attribute value is specified—the color red—a second value is implied. This starting value is computed from the DOM via getComputedStyle or getAttribute.

In some cases, the computed starting value may not be what you want. For example, it can be different than what was set previously due to browsers converting values to canonical representations, say converting the color string "red" to "rgb(255,0,0)". Depending on the interpolator you use (more on that in a bit), this may cause the transition to stutter. As another example, transparent colors are reported as "rgba(0,0,0,0)" (transparent black), which is treated as opaque black when using RGB interpolation.

One way to make the starting value more explicit is to set it in the DOM before creating the transition. This won’t fix problems related to value conversion, but it can be useful if the inherited or default value isn’t what you want.

d3.select("body")
    .style("color", "green") // make the body green
  .transition()
    .style("color", "red"); // then transition to red

If the transition has a delay, then the starting value should be set only when the transition starts. You can do this by listening for the start event:

This is a new feature in 3.0; older versions of D3 dispatched the start event after constructing tweens.

d3.select("body").transition()
    .delay(750)
    .each("start", function() { d3.select(this).style("color", "green"); })
    .style("color", "red");

The most explicit approach to set the starting value is to use transition.styleTween. This skips computing the starting value from the DOM by specifying the both values and an interpolator.

d3.select("body").transition()
    .styleTween("color", function() { return d3.interpolate("green", "red"); });

This last variation gives a hint as to how transitions work under the hood. When you use transition.style, D3 creates a style tween for you automatically by retrieving the starting value from the DOM and constructing an interpolator to the specified ending value. If you want to override the start value or the interpolator, do this using styleTweenattrTween or tween.

#Transitions Interpolate Values over Time

Given start and end key frames, how do we get from here to there? To perform a smooth animated transition, D3 needs to know how to interpolate—or blend—from a given starting value to its corresponding ending value. The d3.interpolate method determines an appropriate interpolator by inferring a type for each pair of starting and ending values. D3 supports several common types, including:

The same interpolation subsystem is used by D3’squantitative scales. You can extend the set of built-in interpolators by adding to thed3.interpolators array. Or create a custom tween.

  • numbers
  • colors
  • geometric transforms
  • strings with embedded numbers (e.g., "96px") (注意,这是目前能够应用transition的几种属性)

The string interpolator is particularly useful: it finds numbers embedded within strings, pairing up numbers in the starting string with the corresponding number in the ending string. Those numbers are interpolated separately, and the resulting string is then reconstructed. String interpolators have myriad applications, such as interpolating path data (e.g., "M0,0L20,30") and CSS font specifications (e.g., "300 12px/100% Helvetica").

String interpolation isn’t always appropriate. If the starting and ending path data have a different number of control points, for example, it’s no longer meaningful to pair up numbers. Instead, you need to resample the path prior to interpolation (or apply more advanced shape blending algorithms). Likewise, arcs require interpolation in polar coordinates so that the angles are interpolated, rather than the positions.

If you want to implement your own interpolator, you need a function that takes a single argument tranging from 0 to 1. For t = 0, the interpolator returns the starting value; for t = 1, the interpolator returns the ending value; and for values in-between, the interpolator returns a blending value. For example, to interpolate two numbers:

When rolling your own interpolator, you may still be able to reuse some of D3’sbuilt-in interpolators.

function interpolateNumber(a, b) {
  return function(t) {
    return a + t * (b - a);
  };
}

When interpolating to or from zero, some interpolated values may be very small. JavaScript formats small numbers in exponential notation, which unfortunately is not supported by CSS. For example, when transitioning opacity to fade in or out, the number 0.0000001 is converted to the string "1e-7" and then ignored, giving the default value of 1! To avoid distracting flicker, start or end the transition at 1e-6 rather than 0; this is the smallest value not formatted in exponential notation.

Some Things Cannot Be Interpolated

When modifying the DOM, use selections for any changes that cannot be interpolated; only use transitions for animation. For example, it is impossible to interpolate the creation of an element: it either exists or it doesn’t. Furthermore, in order to schedule a transition, the element must exist and so element creation cannot be deferred to start. Selection methods related to data joins (data, enter, exit) and creating elements (append, insert) can therefore only be performed on selections.

When using transitions in conjunction with the general update pattern, first perform the data-join on selections using enter and exit. Then derive transitions on each subselection as desired.

To perform a special transition on updating nodes, derive a transition before appending to the enter selection.

(以下是一个常用的使用transition加enter(), exit()集合的一个模板)var bar = svg.selectAll(".bar")
    .data(data, function(d) { return d.key; });

bar.enter().append("rect")
    .attr("class", "bar")
    … // initialize entering bars

bar.transition()
    … // transition entering + updating bars

bar.exit().transition()
    … // transition exiting bars
    .remove();

For convenience, there are a few exceptions to this rule. You can transition.remove to remove an element at the end of the transition; likewise, transition.text sets the text content at the start of the transition, without interpolating. In the future, transitions may support additional non-interpolatable operations, such as classed and html.

#The Life of a Transition

As with concurrent programming, perhaps the trickiest aspect of transitions is that they happen over time rather than instantaneously. The code does not proceed in a single straightforward path, as when the page loads, but as a complex sequence of recurring callbacks. While you can safely ignore this complexity in many cases, you must understand the rules which govern the evaluation of transitions if you want to harness their full power.

A useful mnemonic is that transitions are conceivedborn,live and die. But perhaps that takes the metaphor too literally.

Transitions have a four-phase life cycle:

  1. The transition is scheduled.
  2. The transition starts.
  3. The transition runs.
  4. The transition ends.

A transition is scheduled when it is created: when you call selection.transition, you are scheduling a transition. This is also when you call attrstyle, and other transition methods to define the ending key frame. Scheduling happens in your code (for example, in response to the user clicking a button), meaning that the code so far is fully synchronous. This makes it easier to debug, and easier to use ending values that depend on changing global state, such as a scale’s domain.

A transition starts based on its delay, which was specified when the transition was scheduled. If no delay was specified, then the transition starts as soon as possible, which is typically after a few milliseconds. The start event is then dispatched, and the transition initializes its tweens, which may involve retrieving starting values from the DOM and constructing interpolators. Deferring the initialization of tweens to start is necessary because starting values aren’t known until the transition starts. Therefore, if you use attrTweenstyleTween and other tween methods, keep in mind that your code will be evaluated asynchronously when the transition starts!

While the transition runs, its tweens are repeatedly invoked with values of t ranging from 0 to 1. In addition to delay and duration, transitions have easing to control timing. Easing distorts time, such as for slow-in and slow-out. Some easing functions may temporarily give values of t greater than 1 or less than 0; however, the ending time is always exactly 1 so that the ending value is set exactly when the transition ends. A transition ends based on the sum of its delay and duration. When a transition ends, the tweens are invoked a final time with t = 1, and then the end event is dispatched.

#Transitions Are per-Element and Exclusive

There is no end event when all selected elements finish transitioning, although you can simulate this by counting.

Each element transitions independently. When you create a transition from a selection, think of it as a set of transitions, one per element, rather than a single mega-transition running on multiple elements. Different elements can have different delays and duration, and even different easing and tweens. Additionally, transition events are dispatched separately for each element. When you receive an end event for a given element, its transition has ended, but other transitions may still be running on other elements.

For a given element, transitions are exclusive: only one transition can be running on the element at the same time. Starting a new transition on the element stops any transition that is already running. Interrupting a transition on the element has no effect on other elements, and multiple transitions can run concurrently on different elements. While only one transition can be running simultaneously on the element, multiple transitions can be scheduled. For example, you can schedule successive transitions using transition.transition, which creates a new transition whose delay immediately follows the existing transition.

For each element, sequences of transitions only advance forward in time. Transitions are assigned a monotonically-increasing identifier (id) when they are scheduled; each new transition idis greater than the last. When a transition starts on the element, it can only run if the transition is newer than whatever previously ran on the same element. Thus, starting a new transition implicitly cancels any previous transitions—even if those old transitions have not yet started. This design eliminates the need to cancel transitions explicitly. An excellent illustration of this behavior is thestacked-to-grouped bar transition. This uses two chained transitions: the bars first slide right and narrow; then the bars drop to the baseline. The first transition also has a staggered delay. If you quickly toggle between stacked and grouped, notice the old transition is only interrupted when the new one starts, not when the new one is scheduled.

Similar to how data is bound to an element’s __data__ property, transitions are bound to a__transition__ property. When a transition is first scheduled on an element, this property is created; when the last scheduled transition ends, this property is likewise deleted. Inspecting this property in the console can be useful to debug which transitions are scheduled to run on which elements, as well as to inspect computed tweens and transition timing parameters. Because transitions are bound to elements, you can also reselect elements within a transition and modify tweens or timing. This is most common in conjunction with component-driven transitions, such as the axis component; use post-selection to customize the appearance of elements after invoking the component.

#Additional Reading

This tutorial covered most of the important details in the mechanics of transitions. I omitted an explanation of transition inheritance using transition.each; perhaps I’ll cover that in the future, though see #400 for an example. For more on how transitions should be used (and not just implemented), see my earlier post on object constancy and Heer & Robertson’s excellent paper,“Animated Transitions in Statistical Data Graphics”.

时间: 2024-11-06 18:52:01

D3中动画(transition函数)的使用的相关文章

jQuery动画高级用法(上)——详解animation中的.queue()函数

如果你拿着一个疑问去找专业人士寻找答案,那么你的一个疑问会变成三个,因为他会用另外两个令你更加一头雾水的名词来解释你的这个疑问. 我想这是大多数,包括我在内,IT人在学习过程中碰到的最大问题.当你有一段代码或是一个概念不是很清楚,百度也好,Google也好,在论坛发问也好,给出的答案往往又会夹杂着更多你不懂得概念和令你头疼的代码. 我亦是吃了同样的亏,痛定思痛,决定对animate方面做一些总结,希望能给大家一些启发和帮助 从一个实际应用谈起 今天不谈animate().fadeIn().fad

<转>jQuery动画高级用法(上)——详解animation中的.queue()函数

如果你拿着一个疑问去找专业人士寻找答案,那么你的一个疑问会变成三个,因为他会用另外两个令你更加一头雾水的名词来解释你的这个疑问. 我想这是大多数,包括我在内,IT人在学习过程中碰到的最大问题.当你有一段代码或是一个概念不是很清楚,百度也好,Google也好,在论坛发问也好,给出的答案往往又会夹杂着更多你不懂得概念和令你头疼的代码. 我亦是吃了同样的亏,痛定思痛,决定对animate方面做一些总结,希望能给大家一些启发和帮助 从一个实际应用谈起 今天不谈animate().fadeIn().fad

D3.js 动画 过渡效果 (V3版本)

一 . 过渡的启动 启动过渡效果,与以下四个方法相关: d3.transition([selection],[name]) //创建一个过渡对象.但是由于每个选择集中都有transition()方法,可用d3.select("rect").transition()的方式来创建过渡,因此一般不直接用d3.transition(). transition.delay([delay]) //设定延迟的时间.过渡会经过一定时间后才开始发生.单位是毫秒. transition.duration(

锋利的jQuery读书笔记---jQuery中动画

jQuery中的动画: 1.show和hide 2.fadeIn和fadeOut 3.slideUp和slideDown <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <script type="text/javascript" src="../../js/jquery-2.1.3.js">

jQuery中动画animate(下)

jQuery中动画animate(下) animate在执行动画中,如果需要观察动画的一些执行情况,或者在动画进行中的某一时刻进行一些其他处理,我们可以通过animate提供的第二种设置语法,传递一个对象参数,可以拿到动画执行状态一些通知 .animate( properties, options ) options参数 duration - 设置动画执行的时间 easing - 规定要使用的 easing 函数,过渡使用哪种缓动函数 step:规定每个动画的每一步完成之后要执行的函数 prog

jQuery中动画animate(上)

jQuery中动画animate(上) 有些复杂的动画通过之前学到的几个动画函数是不能够实现,这时候就需要强大的animate方法了 操作一个元素执行3秒的淡入动画,对比一下2组动画设置的区别 $(elem).fadeOut(3000) $(elem).animate({ opacity:0 },3000) 显而易见,animate方法更加灵活了,可以精确的控制样式属性从而执行动画 语法: .animate( properties ,[ duration ], [ easing ], [ com

理解javascript中的回调函数(callback)【转】

在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String.Array.Number.Object类的对象一样用于内置对象的管理.因为function实际上是一种对象,它可以"存储在变量中,通过参数传递给(别一个)函数(function),在函数内部创建,从函数中返回结果值". 因为function是内置对象,我们可以将它作为参数传递给另一个函数,延迟到函数中执行,甚至执行后将它返回.这是在JavaScript中使用回调函数的精髓.本篇文

css3中的transition渐变过渡属性的认识.

css3新增的属性transition可以让元素产生动画效果: 用法(兼容代码): -webkit-transition:property(属性样式) duration(过渡时间) timing-function过渡模式(5种过渡模式效果) -moz-transition:property(属性样式) duration(过渡时间) timing-function过渡模式(5种过渡模式效果) -o-transition:property(属性样式) duration(过渡时间) timing-fu

Unity3D中组件事件函数的执行顺序

事件函数的执行顺序 Unity 脚本中有许多按预设顺序以脚本身份运行的事件函数.其执行顺序如下: 加载第一个场景 启动场景时调用这些函数(为场景中的每个对象调用一次). Awake: 始终在调用任何 Start 函数之前和实例化预设之后调用此函数.(如果游戏对象 (GameObject) 在启动期间处于非活动状态,则直到其处于活动状态时或调用添加至其本身的任何脚本中的函数时,再调用 Awake 函数.) OnEnable: (仅当对象 (Object) 处于活动状态时调用此函数):程序会在启用该