|
1 function d3_transition(groups, id, time) { |
|
2 d3_arraySubclass(groups, d3_transitionPrototype); |
|
3 |
|
4 var tweens = {}, |
|
5 event = d3.dispatch("start", "end"), |
|
6 ease = d3_transitionEase; |
|
7 |
|
8 groups.id = id; |
|
9 |
|
10 groups.time = time; |
|
11 |
|
12 groups.tween = function(name, tween) { |
|
13 if (arguments.length < 2) return tweens[name]; |
|
14 if (tween == null) delete tweens[name]; |
|
15 else tweens[name] = tween; |
|
16 return groups; |
|
17 }; |
|
18 |
|
19 groups.ease = function(value) { |
|
20 if (!arguments.length) return ease; |
|
21 ease = typeof value === "function" ? value : d3.ease.apply(d3, arguments); |
|
22 return groups; |
|
23 }; |
|
24 |
|
25 groups.each = function(type, listener) { |
|
26 if (arguments.length < 2) return d3_transition_each.call(groups, type); |
|
27 event.on(type, listener); |
|
28 return groups; |
|
29 }; |
|
30 |
|
31 d3.timer(function(elapsed) { |
|
32 groups.each(function(d, i, j) { |
|
33 var tweened = [], |
|
34 node = this, |
|
35 delay = groups[j][i].delay, |
|
36 duration = groups[j][i].duration, |
|
37 lock = node.__transition__ || (node.__transition__ = {active: 0, count: 0}); |
|
38 |
|
39 ++lock.count; |
|
40 |
|
41 delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time); |
|
42 |
|
43 function start(elapsed) { |
|
44 if (lock.active > id) return stop(); |
|
45 lock.active = id; |
|
46 |
|
47 for (var tween in tweens) { |
|
48 if (tween = tweens[tween].call(node, d, i)) { |
|
49 tweened.push(tween); |
|
50 } |
|
51 } |
|
52 |
|
53 event.start.call(node, d, i); |
|
54 if (!tick(elapsed)) d3.timer(tick, 0, time); |
|
55 return 1; |
|
56 } |
|
57 |
|
58 function tick(elapsed) { |
|
59 if (lock.active !== id) return stop(); |
|
60 |
|
61 var t = (elapsed - delay) / duration, |
|
62 e = ease(t), |
|
63 n = tweened.length; |
|
64 |
|
65 while (n > 0) { |
|
66 tweened[--n].call(node, e); |
|
67 } |
|
68 |
|
69 if (t >= 1) { |
|
70 stop(); |
|
71 d3_transitionInheritId = id; |
|
72 event.end.call(node, d, i); |
|
73 d3_transitionInheritId = 0; |
|
74 return 1; |
|
75 } |
|
76 } |
|
77 |
|
78 function stop() { |
|
79 if (!--lock.count) delete node.__transition__; |
|
80 return 1; |
|
81 } |
|
82 }); |
|
83 return 1; |
|
84 }, 0, time); |
|
85 |
|
86 return groups; |
|
87 } |
|
88 |
|
89 var d3_transitionRemove = {}; |
|
90 |
|
91 function d3_transitionNull(d, i, a) { |
|
92 return a != "" && d3_transitionRemove; |
|
93 } |
|
94 |
|
95 function d3_transitionTween(name, b) { |
|
96 var interpolate = d3_interpolateByName(name); |
|
97 |
|
98 function transitionFunction(d, i, a) { |
|
99 var v = b.call(this, d, i); |
|
100 return v == null |
|
101 ? a != "" && d3_transitionRemove |
|
102 : a != v && interpolate(a, v); |
|
103 } |
|
104 |
|
105 function transitionString(d, i, a) { |
|
106 return a != b && interpolate(a, b); |
|
107 } |
|
108 |
|
109 return typeof b === "function" ? transitionFunction |
|
110 : b == null ? d3_transitionNull |
|
111 : (b += "", transitionString); |
|
112 } |
|
113 |
|
114 var d3_transitionPrototype = [], |
|
115 d3_transitionId = 0, |
|
116 d3_transitionInheritId = 0, |
|
117 d3_transitionEase = d3.ease("cubic-in-out"); |
|
118 |
|
119 d3_transitionPrototype.call = d3_selectionPrototype.call; |
|
120 |
|
121 d3.transition = function() { |
|
122 return d3_selectionRoot.transition(); |
|
123 }; |
|
124 |
|
125 d3.transition.prototype = d3_transitionPrototype; |