OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2014 Google Inc. All rights reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style | |
5 * license that can be found in the LICENSE file or at | |
6 * https://developers.google.com/open-source/licenses/bsd | |
7 */ | |
8 part of charted.selection.transition; | |
9 | |
10 // handle transitions on an element-basis, so we can cancel if another is | |
11 // scheduled | |
12 Map<Element, int> _transitionMap = {}; | |
13 | |
14 class _TransitionImpl implements Transition { | |
15 SelectionCallback _delay = (d, i, c) => 0; | |
16 SelectionCallback _duration = | |
17 (d, i, c) => Transition.defaultDurationMilliseconds; | |
18 Selection _selection; | |
19 Map _attrs = {}; | |
20 Map _styles = {}; | |
21 Map _attrTweens = {}; | |
22 Map _styleTweens = {}; | |
23 Map<AnimationTimer, Element> _timerMap = {}; | |
24 Map<Element, List<Map>> _attrMap = {}; | |
25 Map<Element, int> _durationMap = {}; | |
26 bool _interrupted = false; | |
27 bool _remove = false; | |
28 var _timerDelay = 0; | |
29 | |
30 _TransitionImpl(this._selection, [num delay = 0]) { | |
31 _transitionNode(delay); | |
32 _timerDelay = delay; | |
33 } | |
34 | |
35 Interpolator ease = clampEasingFn( | |
36 Transition.defaultEasingMode(Transition.defaultEasingType)); | |
37 | |
38 void delay(int millisecond) { | |
39 delayWithCallback(toCallback(millisecond)); | |
40 } | |
41 | |
42 void delayWithCallback(SelectionCallback fn) { | |
43 _delay = fn; | |
44 } | |
45 | |
46 void duration(int millisecond) { | |
47 durationWithCallback(toCallback(millisecond)); | |
48 } | |
49 | |
50 void durationWithCallback(SelectionCallback fn) { | |
51 _duration = fn; | |
52 } | |
53 | |
54 void attr(String name, val) { | |
55 attrWithCallback(name, toCallback(val)); | |
56 } | |
57 | |
58 void attrWithCallback(String name, SelectionCallback fn) { | |
59 _attrs[name] = fn; | |
60 } | |
61 | |
62 void attrTween(String name, AttrTweenCallback tween) { | |
63 _attrTweens[name] = tween; | |
64 } | |
65 | |
66 void style(String property, String val, [String priority = '']) { | |
67 styleWithCallback(property, toCallback(val), priority); | |
68 } | |
69 | |
70 void styleWithCallback(String property, SelectionCallback<String> fn, | |
71 [String priority = '']) { | |
72 _styles[property] = {'callback': fn, 'priority': priority}; | |
73 } | |
74 | |
75 void styleTween(String property, StyleTweenCallback tween, | |
76 [String priority]) { | |
77 _styleTweens[property] = {'callback': tween, 'priority': priority}; | |
78 } | |
79 | |
80 // Starts a timer that registers all attributes, durations, and delays for the | |
81 // transition of the current selection. | |
82 _transitionNode(num delay) { | |
83 new AnimationTimer((elapsed) { | |
84 _selection.each((d, i, c) { | |
85 var tweenList = []; | |
86 _attrs.forEach((key, value) { | |
87 tweenList.add(_getAttrInterpolator(c, key, value(d, i, c))); | |
88 }); | |
89 _attrTweens.forEach((key, value) { | |
90 tweenList.add((t) => c.setAttribute(key, | |
91 value(d, i, c.getAttribute(key))(t))); | |
92 }); | |
93 _styles.forEach((key, value) { | |
94 tweenList.add(_getStyleInterpolator(c, key, | |
95 value['callback'](d, i, c), value['priority'])); | |
96 }); | |
97 _styleTweens.forEach((key, value) { | |
98 tweenList.add((t) => c.style.setProperty(key, | |
99 value['callback'](d, i, | |
100 c.style.getPropertyValue(key))(t).toString(), value['priority'])); | |
101 }); | |
102 | |
103 _attrMap[c] = tweenList; | |
104 _durationMap[c] = _duration(d, i, c); | |
105 _timerMap[new AnimationTimer(_tick, delay: _delay(d, i, c))] = c; | |
106 | |
107 if(!_transitionMap.containsKey(c)) { | |
108 _transitionMap[c] = 1; | |
109 } else { | |
110 _transitionMap[c]++; | |
111 } | |
112 }); | |
113 return true; | |
114 }, delay: delay); | |
115 } | |
116 | |
117 // Returns the correct interpolator function for the old and new attribute. | |
118 _getAttrInterpolator(Element element, String attrName, newValue) { | |
119 var attr = element.attributes[attrName]; | |
120 var interpolator = createStringInterpolator(attr, newValue.toString()); | |
121 return (t) => element.setAttribute(attrName, interpolator(t).toString()); | |
122 } | |
123 | |
124 // Returns the correct interpolator function for the old and new style. | |
125 _getStyleInterpolator(Element element, String styleName, newValue, priority) { | |
126 var style = element.style.getPropertyValue(styleName); | |
127 | |
128 var interpolator = createStringInterpolator(style, newValue.toString()); | |
129 | |
130 return (t) => element.style.setProperty(styleName, | |
131 interpolator(t).toString(), priority); | |
132 } | |
133 | |
134 // Ticks of the transition, this is the callback registered to the | |
135 // ChartedTimer, called on each animation frame until the transition duration | |
136 // has been reached. | |
137 bool _tick(elapsed) { | |
138 if (_interrupted) { | |
139 return true; | |
140 } | |
141 var activeNode = _timerMap[AnimationTimer.active]; | |
142 var t = elapsed / _durationMap[activeNode]; | |
143 for (Interpolator tween in _attrMap[activeNode]) { | |
144 tween(ease(t)); | |
145 } | |
146 | |
147 if (t >= 1) { | |
148 if (_remove && _transitionMap[activeNode] == 1) { | |
149 activeNode.remove(); | |
150 } | |
151 | |
152 if(_transitionMap[activeNode] > 1) { | |
153 _transitionMap[activeNode]--; | |
154 } else { | |
155 _transitionMap.remove(activeNode); | |
156 } | |
157 | |
158 return true; | |
159 } | |
160 | |
161 return false; | |
162 } | |
163 | |
164 // Interrupts the transition. | |
165 void interrupt() { | |
166 _interrupted = true; | |
167 } | |
168 | |
169 Transition select(String selector) { | |
170 var t = new Transition(_selection.select(selector)); | |
171 t.ease = ease; | |
172 t.delayWithCallback(_delay); | |
173 t.durationWithCallback(_duration); | |
174 return t; | |
175 } | |
176 | |
177 Transition selectAll(String selector) { | |
178 var t = new Transition(_selection.selectAll(selector)); | |
179 t.ease = ease; | |
180 t.delayWithCallback(_delay); | |
181 t.durationWithCallback(_duration); | |
182 return t; | |
183 } | |
184 | |
185 Transition transition() { | |
186 var e = _selection.first; | |
187 var delay = _delay(_selection.scope.datum(e), 0, e) + | |
188 _duration(_selection.scope.datum(e), 0, e) + _timerDelay; | |
189 var t = new _TransitionImpl(_selection, delay); | |
190 t.ease = ease; | |
191 t.durationWithCallback(_duration); | |
192 return t; | |
193 } | |
194 | |
195 void remove() { | |
196 _remove = true; | |
197 } | |
198 } | |
OLD | NEW |