source: node_modules/d3-transition/src/transition/schedule.js@ ba17441

Last change on this file since ba17441 was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 4.5 KB
Line 
1import {dispatch} from "d3-dispatch";
2import {timer, timeout} from "d3-timer";
3
4var emptyOn = dispatch("start", "end", "cancel", "interrupt");
5var emptyTween = [];
6
7export var CREATED = 0;
8export var SCHEDULED = 1;
9export var STARTING = 2;
10export var STARTED = 3;
11export var RUNNING = 4;
12export var ENDING = 5;
13export var ENDED = 6;
14
15export default function(node, name, id, index, group, timing) {
16 var schedules = node.__transition;
17 if (!schedules) node.__transition = {};
18 else if (id in schedules) return;
19 create(node, id, {
20 name: name,
21 index: index, // For context during callback.
22 group: group, // For context during callback.
23 on: emptyOn,
24 tween: emptyTween,
25 time: timing.time,
26 delay: timing.delay,
27 duration: timing.duration,
28 ease: timing.ease,
29 timer: null,
30 state: CREATED
31 });
32}
33
34export function init(node, id) {
35 var schedule = get(node, id);
36 if (schedule.state > CREATED) throw new Error("too late; already scheduled");
37 return schedule;
38}
39
40export function set(node, id) {
41 var schedule = get(node, id);
42 if (schedule.state > STARTED) throw new Error("too late; already running");
43 return schedule;
44}
45
46export function get(node, id) {
47 var schedule = node.__transition;
48 if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found");
49 return schedule;
50}
51
52function create(node, id, self) {
53 var schedules = node.__transition,
54 tween;
55
56 // Initialize the self timer when the transition is created.
57 // Note the actual delay is not known until the first callback!
58 schedules[id] = self;
59 self.timer = timer(schedule, 0, self.time);
60
61 function schedule(elapsed) {
62 self.state = SCHEDULED;
63 self.timer.restart(start, self.delay, self.time);
64
65 // If the elapsed delay is less than our first sleep, start immediately.
66 if (self.delay <= elapsed) start(elapsed - self.delay);
67 }
68
69 function start(elapsed) {
70 var i, j, n, o;
71
72 // If the state is not SCHEDULED, then we previously errored on start.
73 if (self.state !== SCHEDULED) return stop();
74
75 for (i in schedules) {
76 o = schedules[i];
77 if (o.name !== self.name) continue;
78
79 // While this element already has a starting transition during this frame,
80 // defer starting an interrupting transition until that transition has a
81 // chance to tick (and possibly end); see d3/d3-transition#54!
82 if (o.state === STARTED) return timeout(start);
83
84 // Interrupt the active transition, if any.
85 if (o.state === RUNNING) {
86 o.state = ENDED;
87 o.timer.stop();
88 o.on.call("interrupt", node, node.__data__, o.index, o.group);
89 delete schedules[i];
90 }
91
92 // Cancel any pre-empted transitions.
93 else if (+i < id) {
94 o.state = ENDED;
95 o.timer.stop();
96 o.on.call("cancel", node, node.__data__, o.index, o.group);
97 delete schedules[i];
98 }
99 }
100
101 // Defer the first tick to end of the current frame; see d3/d3#1576.
102 // Note the transition may be canceled after start and before the first tick!
103 // Note this must be scheduled before the start event; see d3/d3-transition#16!
104 // Assuming this is successful, subsequent callbacks go straight to tick.
105 timeout(function() {
106 if (self.state === STARTED) {
107 self.state = RUNNING;
108 self.timer.restart(tick, self.delay, self.time);
109 tick(elapsed);
110 }
111 });
112
113 // Dispatch the start event.
114 // Note this must be done before the tween are initialized.
115 self.state = STARTING;
116 self.on.call("start", node, node.__data__, self.index, self.group);
117 if (self.state !== STARTING) return; // interrupted
118 self.state = STARTED;
119
120 // Initialize the tween, deleting null tween.
121 tween = new Array(n = self.tween.length);
122 for (i = 0, j = -1; i < n; ++i) {
123 if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
124 tween[++j] = o;
125 }
126 }
127 tween.length = j + 1;
128 }
129
130 function tick(elapsed) {
131 var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
132 i = -1,
133 n = tween.length;
134
135 while (++i < n) {
136 tween[i].call(node, t);
137 }
138
139 // Dispatch the end event.
140 if (self.state === ENDING) {
141 self.on.call("end", node, node.__data__, self.index, self.group);
142 stop();
143 }
144 }
145
146 function stop() {
147 self.state = ENDED;
148 self.timer.stop();
149 delete schedules[id];
150 for (var i in schedules) return; // eslint-disable-line no-unused-vars
151 delete node.__transition;
152 }
153}
Note: See TracBrowser for help on using the repository browser.