Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4
5 /** 4 /**
6 * @constructor 5 * @unrestricted
7 * @param {!WebInspector.AnimationModel.Animation} animation
8 * @param {!WebInspector.AnimationTimeline} timeline
9 * @param {!Element} parentElement
10 */ 6 */
11 WebInspector.AnimationUI = function(animation, timeline, parentElement) { 7 WebInspector.AnimationUI = class {
8 /**
9 * @param {!WebInspector.AnimationModel.Animation} animation
10 * @param {!WebInspector.AnimationTimeline} timeline
11 * @param {!Element} parentElement
12 */
13 constructor(animation, timeline, parentElement) {
12 this._animation = animation; 14 this._animation = animation;
13 this._timeline = timeline; 15 this._timeline = timeline;
14 this._parentElement = parentElement; 16 this._parentElement = parentElement;
15 17
16 if (this._animation.source().keyframesRule()) 18 if (this._animation.source().keyframesRule())
17 this._keyframes = this._animation.source().keyframesRule().keyframes(); 19 this._keyframes = this._animation.source().keyframesRule().keyframes();
18 20
19 this._nameElement = parentElement.createChild("div", "animation-name"); 21 this._nameElement = parentElement.createChild('div', 'animation-name');
20 this._nameElement.textContent = this._animation.name(); 22 this._nameElement.textContent = this._animation.name();
21 23
22 this._svg = parentElement.createSVGChild("svg", "animation-ui"); 24 this._svg = parentElement.createSVGChild('svg', 'animation-ui');
23 this._svg.setAttribute("height", WebInspector.AnimationUI.Options.AnimationS VGHeight); 25 this._svg.setAttribute('height', WebInspector.AnimationUI.Options.AnimationS VGHeight);
24 this._svg.style.marginLeft = "-" + WebInspector.AnimationUI.Options.Animatio nMargin + "px"; 26 this._svg.style.marginLeft = '-' + WebInspector.AnimationUI.Options.Animatio nMargin + 'px';
25 this._svg.addEventListener("contextmenu", this._onContextMenu.bind(this)); 27 this._svg.addEventListener('contextmenu', this._onContextMenu.bind(this));
26 this._activeIntervalGroup = this._svg.createSVGChild("g"); 28 this._activeIntervalGroup = this._svg.createSVGChild('g');
27 WebInspector.installDragHandle(this._activeIntervalGroup, this._mouseDown.bi nd(this, WebInspector.AnimationUI.MouseEvents.AnimationDrag, null), this._mouse Move.bind(this), this._mouseUp.bind(this), "-webkit-grabbing", "-webkit-grab"); 29 WebInspector.installDragHandle(
30 this._activeIntervalGroup, this._mouseDown.bind(this, WebInspector.Anima tionUI.MouseEvents.AnimationDrag, null),
31 this._mouseMove.bind(this), this._mouseUp.bind(this), '-webkit-grabbing' , '-webkit-grab');
28 32
29 /** @type {!Array.<{group: ?Element, animationLine: ?Element, keyframePoints : !Object.<number, !Element>, keyframeRender: !Object.<number, !Element>}>} */ 33 /** @type {!Array.<{group: ?Element, animationLine: ?Element, keyframePoints : !Object.<number, !Element>, keyframeRender: !Object.<number, !Element>}>} */
30 this._cachedElements = []; 34 this._cachedElements = [];
31 35
32 this._movementInMs = 0; 36 this._movementInMs = 0;
33 this._color = WebInspector.AnimationUI.Color(this._animation); 37 this._color = WebInspector.AnimationUI.Color(this._animation);
38 }
39
40 /**
41 * @param {!WebInspector.AnimationModel.Animation} animation
42 * @return {string}
43 */
44 static Color(animation) {
45 var names = Object.keys(WebInspector.AnimationUI.Colors);
46 var color =
47 WebInspector.AnimationUI.Colors[names[String.hashCode(animation.name() | | animation.id()) % names.length]];
48 return color.asString(WebInspector.Color.Format.RGB);
49 }
50
51 /**
52 * @return {!WebInspector.AnimationModel.Animation}
53 */
54 animation() {
55 return this._animation;
56 }
57
58 /**
59 * @param {?WebInspector.DOMNode} node
60 */
61 setNode(node) {
62 this._node = node;
63 }
64
65 /**
66 * @param {!Element} parentElement
67 * @param {string} className
68 */
69 _createLine(parentElement, className) {
70 var line = parentElement.createSVGChild('line', className);
71 line.setAttribute('x1', WebInspector.AnimationUI.Options.AnimationMargin);
72 line.setAttribute('y1', WebInspector.AnimationUI.Options.AnimationHeight);
73 line.setAttribute('y2', WebInspector.AnimationUI.Options.AnimationHeight);
74 line.style.stroke = this._color;
75 return line;
76 }
77
78 /**
79 * @param {number} iteration
80 * @param {!Element} parentElement
81 */
82 _drawAnimationLine(iteration, parentElement) {
83 var cache = this._cachedElements[iteration];
84 if (!cache.animationLine)
85 cache.animationLine = this._createLine(parentElement, 'animation-line');
86 cache.animationLine.setAttribute(
87 'x2', (this._duration() * this._timeline.pixelMsRatio() + WebInspector.A nimationUI.Options.AnimationMargin)
88 .toFixed(2));
89 }
90
91 /**
92 * @param {!Element} parentElement
93 */
94 _drawDelayLine(parentElement) {
95 if (!this._delayLine) {
96 this._delayLine = this._createLine(parentElement, 'animation-delay-line');
97 this._endDelayLine = this._createLine(parentElement, 'animation-delay-line ');
98 }
99 var fill = this._animation.source().fill();
100 this._delayLine.classList.toggle('animation-fill', fill === 'backwards' || f ill === 'both');
101 var margin = WebInspector.AnimationUI.Options.AnimationMargin;
102 this._delayLine.setAttribute('x1', margin);
103 this._delayLine.setAttribute('x2', (this._delay() * this._timeline.pixelMsRa tio() + margin).toFixed(2));
104 var forwardsFill = fill === 'forwards' || fill === 'both';
105 this._endDelayLine.classList.toggle('animation-fill', forwardsFill);
106 var leftMargin = Math.min(
107 this._timeline.width(),
108 (this._delay() + this._duration() * this._animation.source().iterations( )) * this._timeline.pixelMsRatio());
109 this._endDelayLine.style.transform = 'translateX(' + leftMargin.toFixed(2) + 'px)';
110 this._endDelayLine.setAttribute('x1', margin);
111 this._endDelayLine.setAttribute(
112 'x2', forwardsFill ? (this._timeline.width() - leftMargin + margin).toFi xed(2) :
113 (this._animation.source().endDelay() * this._timeli ne.pixelMsRatio() + margin).toFixed(2));
114 }
115
116 /**
117 * @param {number} iteration
118 * @param {!Element} parentElement
119 * @param {number} x
120 * @param {number} keyframeIndex
121 * @param {boolean} attachEvents
122 */
123 _drawPoint(iteration, parentElement, x, keyframeIndex, attachEvents) {
124 if (this._cachedElements[iteration].keyframePoints[keyframeIndex]) {
125 this._cachedElements[iteration].keyframePoints[keyframeIndex].setAttribute ('cx', x.toFixed(2));
126 return;
127 }
128
129 var circle =
130 parentElement.createSVGChild('circle', keyframeIndex <= 0 ? 'animation-e ndpoint' : 'animation-keyframe-point');
131 circle.setAttribute('cx', x.toFixed(2));
132 circle.setAttribute('cy', WebInspector.AnimationUI.Options.AnimationHeight);
133 circle.style.stroke = this._color;
134 circle.setAttribute('r', WebInspector.AnimationUI.Options.AnimationMargin / 2);
135
136 if (keyframeIndex <= 0)
137 circle.style.fill = this._color;
138
139 this._cachedElements[iteration].keyframePoints[keyframeIndex] = circle;
140
141 if (!attachEvents)
142 return;
143
144 var eventType;
145 if (keyframeIndex === 0)
146 eventType = WebInspector.AnimationUI.MouseEvents.StartEndpointMove;
147 else if (keyframeIndex === -1)
148 eventType = WebInspector.AnimationUI.MouseEvents.FinishEndpointMove;
149 else
150 eventType = WebInspector.AnimationUI.MouseEvents.KeyframeMove;
151 WebInspector.installDragHandle(
152 circle, this._mouseDown.bind(this, eventType, keyframeIndex), this._mous eMove.bind(this),
153 this._mouseUp.bind(this), 'ew-resize');
154 }
155
156 /**
157 * @param {number} iteration
158 * @param {number} keyframeIndex
159 * @param {!Element} parentElement
160 * @param {number} leftDistance
161 * @param {number} width
162 * @param {string} easing
163 */
164 _renderKeyframe(iteration, keyframeIndex, parentElement, leftDistance, width, easing) {
165 /**
166 * @param {!Element} parentElement
167 * @param {number} x
168 * @param {string} strokeColor
169 */
170 function createStepLine(parentElement, x, strokeColor) {
171 var line = parentElement.createSVGChild('line');
172 line.setAttribute('x1', x);
173 line.setAttribute('x2', x);
174 line.setAttribute('y1', WebInspector.AnimationUI.Options.AnimationMargin);
175 line.setAttribute('y2', WebInspector.AnimationUI.Options.AnimationHeight);
176 line.style.stroke = strokeColor;
177 }
178
179 var bezier = WebInspector.Geometry.CubicBezier.parse(easing);
180 var cache = this._cachedElements[iteration].keyframeRender;
181 if (!cache[keyframeIndex])
182 cache[keyframeIndex] = bezier ? parentElement.createSVGChild('path', 'anim ation-keyframe') :
183 parentElement.createSVGChild('g', 'animati on-keyframe-step');
184 var group = cache[keyframeIndex];
185 group.style.transform = 'translateX(' + leftDistance.toFixed(2) + 'px)';
186
187 if (easing === 'linear') {
188 group.style.fill = this._color;
189 var height = WebInspector.BezierUI.Height;
190 group.setAttribute(
191 'd', ['M', 0, height, 'L', 0, 5, 'L', width.toFixed(2), 5, 'L', width. toFixed(2), height, 'Z'].join(' '));
192 } else if (bezier) {
193 group.style.fill = this._color;
194 WebInspector.BezierUI.drawVelocityChart(bezier, group, width);
195 } else {
196 var stepFunction = WebInspector.AnimationTimeline.StepTimingFunction.parse (easing);
197 group.removeChildren();
198 /** @const */ var offsetMap = {'start': 0, 'middle': 0.5, 'end': 1};
199 /** @const */ var offsetWeight = offsetMap[stepFunction.stepAtPosition];
200 for (var i = 0; i < stepFunction.steps; i++)
201 createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, t his._color);
202 }
203 }
204
205 redraw() {
206 var durationWithDelay =
207 this._delay() + this._duration() * this._animation.source().iterations() + this._animation.source().endDelay();
208 var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options.Ani mationMargin;
209
210 this._svg.setAttribute('width', (maxWidth + 2 * WebInspector.AnimationUI.Opt ions.AnimationMargin).toFixed(2));
211 this._activeIntervalGroup.style.transform =
212 'translateX(' + (this._delay() * this._timeline.pixelMsRatio()).toFixed( 2) + 'px)';
213
214 this._nameElement.style.transform = 'translateX(' +
215 (this._delay() * this._timeline.pixelMsRatio() + WebInspector.AnimationU I.Options.AnimationMargin).toFixed(2) +
216 'px)';
217 this._nameElement.style.width = (this._duration() * this._timeline.pixelMsRa tio()).toFixed(2) + 'px';
218 this._drawDelayLine(this._svg);
219
220 if (this._animation.type() === 'CSSTransition') {
221 this._renderTransition();
222 return;
223 }
224
225 this._renderIteration(this._activeIntervalGroup, 0);
226 if (!this._tailGroup)
227 this._tailGroup = this._activeIntervalGroup.createSVGChild('g', 'animation -tail-iterations');
228 var iterationWidth = this._duration() * this._timeline.pixelMsRatio();
229 for (var iteration = 1;
230 iteration < this._animation.source().iterations() && iterationWidth * ( iteration - 1) < this._timeline.width();
231 iteration++)
232 this._renderIteration(this._tailGroup, iteration);
233 while (iteration < this._cachedElements.length)
234 this._cachedElements.pop().group.remove();
235 }
236
237 _renderTransition() {
238 if (!this._cachedElements[0])
239 this._cachedElements[0] = {animationLine: null, keyframePoints: {}, keyfra meRender: {}, group: null};
240 this._drawAnimationLine(0, this._activeIntervalGroup);
241 this._renderKeyframe(
242 0, 0, this._activeIntervalGroup, WebInspector.AnimationUI.Options.Animat ionMargin,
243 this._duration() * this._timeline.pixelMsRatio(), this._animation.source ().easing());
244 this._drawPoint(0, this._activeIntervalGroup, WebInspector.AnimationUI.Optio ns.AnimationMargin, 0, true);
245 this._drawPoint(
246 0, this._activeIntervalGroup,
247 this._duration() * this._timeline.pixelMsRatio() + WebInspector.Animatio nUI.Options.AnimationMargin, -1, true);
248 }
249
250 /**
251 * @param {!Element} parentElement
252 * @param {number} iteration
253 */
254 _renderIteration(parentElement, iteration) {
255 if (!this._cachedElements[iteration])
256 this._cachedElements[iteration] =
257 {animationLine: null, keyframePoints: {}, keyframeRender: {}, group: p arentElement.createSVGChild('g')};
258 var group = this._cachedElements[iteration].group;
259 group.style.transform =
260 'translateX(' + (iteration * this._duration() * this._timeline.pixelMsRa tio()).toFixed(2) + 'px)';
261 this._drawAnimationLine(iteration, group);
262 console.assert(this._keyframes.length > 1);
263 for (var i = 0; i < this._keyframes.length - 1; i++) {
264 var leftDistance = this._offset(i) * this._duration() * this._timeline.pix elMsRatio() +
265 WebInspector.AnimationUI.Options.AnimationMargin;
266 var width = this._duration() * (this._offset(i + 1) - this._offset(i)) * t his._timeline.pixelMsRatio();
267 this._renderKeyframe(iteration, i, group, leftDistance, width, this._keyfr ames[i].easing());
268 if (i || (!i && iteration === 0))
269 this._drawPoint(iteration, group, leftDistance, i, iteration === 0);
270 }
271 this._drawPoint(
272 iteration, group,
273 this._duration() * this._timeline.pixelMsRatio() + WebInspector.Animatio nUI.Options.AnimationMargin, -1,
274 iteration === 0);
275 }
276
277 /**
278 * @return {number}
279 */
280 _delay() {
281 var delay = this._animation.source().delay();
282 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.AnimationD rag ||
283 this._mouseEventType === WebInspector.AnimationUI.MouseEvents.StartEndpo intMove)
284 delay += this._movementInMs;
285 // FIXME: add support for negative start delay
286 return Math.max(0, delay);
287 }
288
289 /**
290 * @return {number}
291 */
292 _duration() {
293 var duration = this._animation.source().duration();
294 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.FinishEndp ointMove)
295 duration += this._movementInMs;
296 else if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.Start EndpointMove)
297 duration -= Math.max(this._movementInMs, -this._animation.source().delay() ); // Cannot have negative delay
298 return Math.max(0, duration);
299 }
300
301 /**
302 * @param {number} i
303 * @return {number} offset
304 */
305 _offset(i) {
306 var offset = this._keyframes[i].offsetAsNumber();
307 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.KeyframeMo ve && i === this._keyframeMoved) {
308 console.assert(i > 0 && i < this._keyframes.length - 1, 'First and last ke yframe cannot be moved');
309 offset += this._movementInMs / this._animation.source().duration();
310 offset = Math.max(offset, this._keyframes[i - 1].offsetAsNumber());
311 offset = Math.min(offset, this._keyframes[i + 1].offsetAsNumber());
312 }
313 return offset;
314 }
315
316 /**
317 * @param {!WebInspector.AnimationUI.MouseEvents} mouseEventType
318 * @param {?number} keyframeIndex
319 * @param {!Event} event
320 */
321 _mouseDown(mouseEventType, keyframeIndex, event) {
322 if (event.buttons === 2)
323 return false;
324 if (this._svg.enclosingNodeOrSelfWithClass('animation-node-removed'))
325 return false;
326 this._mouseEventType = mouseEventType;
327 this._keyframeMoved = keyframeIndex;
328 this._downMouseX = event.clientX;
329 event.consume(true);
330 if (this._node)
331 WebInspector.Revealer.reveal(this._node);
332 return true;
333 }
334
335 /**
336 * @param {!Event} event
337 */
338 _mouseMove(event) {
339 this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pix elMsRatio();
340 if (this._delay() + this._duration() > this._timeline.duration() * 0.8)
341 this._timeline.setDuration(this._timeline.duration() * 1.2);
342 this.redraw();
343 }
344
345 /**
346 * @param {!Event} event
347 */
348 _mouseUp(event) {
349 this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pix elMsRatio();
350
351 // Commit changes
352 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.KeyframeMo ve)
353 this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframe Moved));
354 else
355 this._animation.setTiming(this._duration(), this._delay());
356
357 this._movementInMs = 0;
358 this.redraw();
359
360 delete this._mouseEventType;
361 delete this._downMouseX;
362 delete this._keyframeMoved;
363 }
364
365 /**
366 * @param {!Event} event
367 */
368 _onContextMenu(event) {
369 /**
370 * @param {?WebInspector.RemoteObject} remoteObject
371 */
372 function showContextMenu(remoteObject) {
373 if (!remoteObject)
374 return;
375 var contextMenu = new WebInspector.ContextMenu(event);
376 contextMenu.appendApplicableItems(remoteObject);
377 contextMenu.show();
378 }
379
380 this._animation.remoteObjectPromise().then(showContextMenu);
381 event.consume(true);
382 }
34 }; 383 };
35 384
36 /** 385 /**
37 * @enum {string} 386 * @enum {string}
38 */ 387 */
39 WebInspector.AnimationUI.MouseEvents = { 388 WebInspector.AnimationUI.MouseEvents = {
40 AnimationDrag: "AnimationDrag", 389 AnimationDrag: 'AnimationDrag',
41 KeyframeMove: "KeyframeMove", 390 KeyframeMove: 'KeyframeMove',
42 StartEndpointMove: "StartEndpointMove", 391 StartEndpointMove: 'StartEndpointMove',
43 FinishEndpointMove: "FinishEndpointMove" 392 FinishEndpointMove: 'FinishEndpointMove'
44 }; 393 };
45 394
46 WebInspector.AnimationUI.prototype = { 395 WebInspector.AnimationUI.Options = {
47 /** 396 AnimationHeight: 26,
48 * @return {!WebInspector.AnimationModel.Animation} 397 AnimationSVGHeight: 50,
49 */ 398 AnimationMargin: 7,
50 animation: function() 399 EndpointsClickRegionSize: 10,
51 { 400 GridCanvasHeight: 40
52 return this._animation;
53 },
54
55 /**
56 * @param {?WebInspector.DOMNode} node
57 */
58 setNode: function(node)
59 {
60 this._node = node;
61 },
62
63 /**
64 * @param {!Element} parentElement
65 * @param {string} className
66 */
67 _createLine: function(parentElement, className)
68 {
69 var line = parentElement.createSVGChild("line", className);
70 line.setAttribute("x1", WebInspector.AnimationUI.Options.AnimationMargin );
71 line.setAttribute("y1", WebInspector.AnimationUI.Options.AnimationHeight );
72 line.setAttribute("y2", WebInspector.AnimationUI.Options.AnimationHeight );
73 line.style.stroke = this._color;
74 return line;
75 },
76
77 /**
78 * @param {number} iteration
79 * @param {!Element} parentElement
80 */
81 _drawAnimationLine: function(iteration, parentElement)
82 {
83 var cache = this._cachedElements[iteration];
84 if (!cache.animationLine)
85 cache.animationLine = this._createLine(parentElement, "animation-lin e");
86 cache.animationLine.setAttribute("x2", (this._duration() * this._timelin e.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2)) ;
87 },
88
89 /**
90 * @param {!Element} parentElement
91 */
92 _drawDelayLine: function(parentElement)
93 {
94 if (!this._delayLine) {
95 this._delayLine = this._createLine(parentElement, "animation-delay-l ine");
96 this._endDelayLine = this._createLine(parentElement, "animation-dela y-line");
97 }
98 var fill = this._animation.source().fill();
99 this._delayLine.classList.toggle("animation-fill", fill === "backwards" || fill === "both");
100 var margin = WebInspector.AnimationUI.Options.AnimationMargin;
101 this._delayLine.setAttribute("x1", margin);
102 this._delayLine.setAttribute("x2", (this._delay() * this._timeline.pixel MsRatio() + margin).toFixed(2));
103 var forwardsFill = fill === "forwards" || fill === "both";
104 this._endDelayLine.classList.toggle("animation-fill", forwardsFill);
105 var leftMargin = Math.min(this._timeline.width(), (this._delay() + this. _duration() * this._animation.source().iterations()) * this._timeline.pixelMsRat io());
106 this._endDelayLine.style.transform = "translateX(" + leftMargin.toFixed( 2) + "px)";
107 this._endDelayLine.setAttribute("x1", margin);
108 this._endDelayLine.setAttribute("x2", forwardsFill
109 ? (this._timeline.width() - leftMargin + margin).toFixed(2)
110 : (this._animation.source().endDelay() * this._timeline.pixelMsRatio () + margin).toFixed(2));
111 },
112
113 /**
114 * @param {number} iteration
115 * @param {!Element} parentElement
116 * @param {number} x
117 * @param {number} keyframeIndex
118 * @param {boolean} attachEvents
119 */
120 _drawPoint: function(iteration, parentElement, x, keyframeIndex, attachEvent s)
121 {
122 if (this._cachedElements[iteration].keyframePoints[keyframeIndex]) {
123 this._cachedElements[iteration].keyframePoints[keyframeIndex].setAtt ribute("cx", x.toFixed(2));
124 return;
125 }
126
127 var circle = parentElement.createSVGChild("circle", keyframeIndex <= 0 ? "animation-endpoint" : "animation-keyframe-point");
128 circle.setAttribute("cx", x.toFixed(2));
129 circle.setAttribute("cy", WebInspector.AnimationUI.Options.AnimationHeig ht);
130 circle.style.stroke = this._color;
131 circle.setAttribute("r", WebInspector.AnimationUI.Options.AnimationMargi n / 2);
132
133 if (keyframeIndex <= 0)
134 circle.style.fill = this._color;
135
136 this._cachedElements[iteration].keyframePoints[keyframeIndex] = circle;
137
138 if (!attachEvents)
139 return;
140
141 var eventType;
142 if (keyframeIndex === 0)
143 eventType = WebInspector.AnimationUI.MouseEvents.StartEndpointMove;
144 else if (keyframeIndex === -1)
145 eventType = WebInspector.AnimationUI.MouseEvents.FinishEndpointMove;
146 else
147 eventType = WebInspector.AnimationUI.MouseEvents.KeyframeMove;
148 WebInspector.installDragHandle(circle, this._mouseDown.bind(this, eventT ype, keyframeIndex), this._mouseMove.bind(this), this._mouseUp.bind(this), "ew-r esize");
149 },
150
151 /**
152 * @param {number} iteration
153 * @param {number} keyframeIndex
154 * @param {!Element} parentElement
155 * @param {number} leftDistance
156 * @param {number} width
157 * @param {string} easing
158 */
159 _renderKeyframe: function(iteration, keyframeIndex, parentElement, leftDista nce, width, easing)
160 {
161 /**
162 * @param {!Element} parentElement
163 * @param {number} x
164 * @param {string} strokeColor
165 */
166 function createStepLine(parentElement, x, strokeColor)
167 {
168 var line = parentElement.createSVGChild("line");
169 line.setAttribute("x1", x);
170 line.setAttribute("x2", x);
171 line.setAttribute("y1", WebInspector.AnimationUI.Options.AnimationMa rgin);
172 line.setAttribute("y2", WebInspector.AnimationUI.Options.AnimationHe ight);
173 line.style.stroke = strokeColor;
174 }
175
176 var bezier = WebInspector.Geometry.CubicBezier.parse(easing);
177 var cache = this._cachedElements[iteration].keyframeRender;
178 if (!cache[keyframeIndex])
179 cache[keyframeIndex] = bezier ? parentElement.createSVGChild("path", "animation-keyframe") : parentElement.createSVGChild("g", "animation-keyframe-s tep");
180 var group = cache[keyframeIndex];
181 group.style.transform = "translateX(" + leftDistance.toFixed(2) + "px)";
182
183 if (easing === "linear") {
184 group.style.fill = this._color;
185 var height = WebInspector.BezierUI.Height;
186 group.setAttribute("d", ["M", 0, height, "L", 0, 5, "L", width.toFix ed(2), 5, "L", width.toFixed(2), height, "Z"].join(" "));
187 } else if (bezier) {
188 group.style.fill = this._color;
189 WebInspector.BezierUI.drawVelocityChart(bezier, group, width);
190 } else {
191 var stepFunction = WebInspector.AnimationTimeline.StepTimingFunction .parse(easing);
192 group.removeChildren();
193 /** @const */ var offsetMap = {"start": 0, "middle": 0.5, "end": 1};
194 /** @const */ var offsetWeight = offsetMap[stepFunction.stepAtPositi on];
195 for (var i = 0; i < stepFunction.steps; i++)
196 createStepLine(group, (i + offsetWeight) * width / stepFunction. steps, this._color);
197 }
198 },
199
200 redraw: function()
201 {
202 var durationWithDelay = this._delay() + this._duration() * this._animati on.source().iterations() + this._animation.source().endDelay();
203 var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options .AnimationMargin;
204
205 this._svg.setAttribute("width", (maxWidth + 2 * WebInspector.AnimationUI .Options.AnimationMargin).toFixed(2));
206 this._activeIntervalGroup.style.transform = "translateX(" + (this._delay () * this._timeline.pixelMsRatio()).toFixed(2) + "px)";
207
208 this._nameElement.style.transform = "translateX(" + (this._delay() * thi s._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin).t oFixed(2) + "px)";
209 this._nameElement.style.width = (this._duration() * this._timeline.pixel MsRatio()).toFixed(2) + "px";
210 this._drawDelayLine(this._svg);
211
212 if (this._animation.type() === "CSSTransition") {
213 this._renderTransition();
214 return;
215 }
216
217 this._renderIteration(this._activeIntervalGroup, 0);
218 if (!this._tailGroup)
219 this._tailGroup = this._activeIntervalGroup.createSVGChild("g", "ani mation-tail-iterations");
220 var iterationWidth = this._duration() * this._timeline.pixelMsRatio();
221 for (var iteration = 1; iteration < this._animation.source().iterations( ) && iterationWidth * (iteration - 1) < this._timeline.width(); iteration++)
222 this._renderIteration(this._tailGroup, iteration);
223 while (iteration < this._cachedElements.length)
224 this._cachedElements.pop().group.remove();
225 },
226
227
228 _renderTransition: function()
229 {
230 if (!this._cachedElements[0])
231 this._cachedElements[0] = { animationLine: null, keyframePoints: {}, keyframeRender: {}, group: null };
232 this._drawAnimationLine(0, this._activeIntervalGroup);
233 this._renderKeyframe(0, 0, this._activeIntervalGroup, WebInspector.Anima tionUI.Options.AnimationMargin, this._duration() * this._timeline.pixelMsRatio() , this._animation.source().easing());
234 this._drawPoint(0, this._activeIntervalGroup, WebInspector.AnimationUI.O ptions.AnimationMargin, 0, true);
235 this._drawPoint(0, this._activeIntervalGroup, this._duration() * this._t imeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1, t rue);
236 },
237
238 /**
239 * @param {!Element} parentElement
240 * @param {number} iteration
241 */
242 _renderIteration: function(parentElement, iteration)
243 {
244 if (!this._cachedElements[iteration])
245 this._cachedElements[iteration] = { animationLine: null, keyframePoi nts: {}, keyframeRender: {}, group: parentElement.createSVGChild("g") };
246 var group = this._cachedElements[iteration].group;
247 group.style.transform = "translateX(" + (iteration * this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + "px)";
248 this._drawAnimationLine(iteration, group);
249 console.assert(this._keyframes.length > 1);
250 for (var i = 0; i < this._keyframes.length - 1; i++) {
251 var leftDistance = this._offset(i) * this._duration() * this._timeli ne.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin;
252 var width = this._duration() * (this._offset(i + 1) - this._offset(i )) * this._timeline.pixelMsRatio();
253 this._renderKeyframe(iteration, i, group, leftDistance, width, this. _keyframes[i].easing());
254 if (i || (!i && iteration === 0))
255 this._drawPoint(iteration, group, leftDistance, i, iteration === 0);
256 }
257 this._drawPoint(iteration, group, this._duration() * this._timeline.pixe lMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1, iteration === 0);
258 },
259
260 /**
261 * @return {number}
262 */
263 _delay: function()
264 {
265 var delay = this._animation.source().delay();
266 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.Animat ionDrag || this._mouseEventType === WebInspector.AnimationUI.MouseEvents.StartEn dpointMove)
267 delay += this._movementInMs;
268 // FIXME: add support for negative start delay
269 return Math.max(0, delay);
270 },
271
272 /**
273 * @return {number}
274 */
275 _duration: function()
276 {
277 var duration = this._animation.source().duration();
278 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.Finish EndpointMove)
279 duration += this._movementInMs;
280 else if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.S tartEndpointMove)
281 duration -= Math.max(this._movementInMs, -this._animation.source().d elay()); // Cannot have negative delay
282 return Math.max(0, duration);
283 },
284
285 /**
286 * @param {number} i
287 * @return {number} offset
288 */
289 _offset: function(i)
290 {
291 var offset = this._keyframes[i].offsetAsNumber();
292 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.Keyfra meMove && i === this._keyframeMoved) {
293 console.assert(i > 0 && i < this._keyframes.length - 1, "First and l ast keyframe cannot be moved");
294 offset += this._movementInMs / this._animation.source().duration();
295 offset = Math.max(offset, this._keyframes[i - 1].offsetAsNumber());
296 offset = Math.min(offset, this._keyframes[i + 1].offsetAsNumber());
297 }
298 return offset;
299 },
300
301 /**
302 * @param {!WebInspector.AnimationUI.MouseEvents} mouseEventType
303 * @param {?number} keyframeIndex
304 * @param {!Event} event
305 */
306 _mouseDown: function(mouseEventType, keyframeIndex, event)
307 {
308 if (event.buttons === 2)
309 return false;
310 if (this._svg.enclosingNodeOrSelfWithClass("animation-node-removed"))
311 return false;
312 this._mouseEventType = mouseEventType;
313 this._keyframeMoved = keyframeIndex;
314 this._downMouseX = event.clientX;
315 event.consume(true);
316 if (this._node)
317 WebInspector.Revealer.reveal(this._node);
318 return true;
319 },
320
321 /**
322 * @param {!Event} event
323 */
324 _mouseMove: function(event)
325 {
326 this._movementInMs = (event.clientX - this._downMouseX) / this._timeline .pixelMsRatio();
327 if (this._delay() + this._duration() > this._timeline.duration() * 0.8)
328 this._timeline.setDuration(this._timeline.duration() * 1.2);
329 this.redraw();
330 },
331
332 /**
333 * @param {!Event} event
334 */
335 _mouseUp: function(event)
336 {
337 this._movementInMs = (event.clientX - this._downMouseX) / this._timeline .pixelMsRatio();
338
339 // Commit changes
340 if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.Keyfra meMove)
341 this._keyframes[this._keyframeMoved].setOffset(this._offset(this._ke yframeMoved));
342 else
343 this._animation.setTiming(this._duration(), this._delay());
344
345 this._movementInMs = 0;
346 this.redraw();
347
348 delete this._mouseEventType;
349 delete this._downMouseX;
350 delete this._keyframeMoved;
351 },
352
353 /**
354 * @param {!Event} event
355 */
356 _onContextMenu: function(event)
357 {
358 /**
359 * @param {?WebInspector.RemoteObject} remoteObject
360 */
361 function showContextMenu(remoteObject)
362 {
363 if (!remoteObject)
364 return;
365 var contextMenu = new WebInspector.ContextMenu(event);
366 contextMenu.appendApplicableItems(remoteObject);
367 contextMenu.show();
368 }
369
370 this._animation.remoteObjectPromise().then(showContextMenu);
371 event.consume(true);
372 }
373 }; 401 };
374 402
375 WebInspector.AnimationUI.Options = { 403 WebInspector.AnimationUI.Colors = {
376 AnimationHeight: 26, 404 'Purple': WebInspector.Color.parse('#9C27B0'),
377 AnimationSVGHeight: 50, 405 'Light Blue': WebInspector.Color.parse('#03A9F4'),
378 AnimationMargin: 7, 406 'Deep Orange': WebInspector.Color.parse('#FF5722'),
379 EndpointsClickRegionSize: 10, 407 'Blue': WebInspector.Color.parse('#5677FC'),
380 GridCanvasHeight: 40 408 'Lime': WebInspector.Color.parse('#CDDC39'),
409 'Blue Grey': WebInspector.Color.parse('#607D8B'),
410 'Pink': WebInspector.Color.parse('#E91E63'),
411 'Green': WebInspector.Color.parse('#0F9D58'),
412 'Brown': WebInspector.Color.parse('#795548'),
413 'Cyan': WebInspector.Color.parse('#00BCD4')
381 }; 414 };
382 415
383 WebInspector.AnimationUI.Colors = { 416
384 "Purple": WebInspector.Color.parse("#9C27B0"),
385 "Light Blue": WebInspector.Color.parse("#03A9F4"),
386 "Deep Orange": WebInspector.Color.parse("#FF5722"),
387 "Blue": WebInspector.Color.parse("#5677FC"),
388 "Lime": WebInspector.Color.parse("#CDDC39"),
389 "Blue Grey": WebInspector.Color.parse("#607D8B"),
390 "Pink": WebInspector.Color.parse("#E91E63"),
391 "Green": WebInspector.Color.parse("#0F9D58"),
392 "Brown": WebInspector.Color.parse("#795548"),
393 "Cyan": WebInspector.Color.parse("#00BCD4")
394 };
395
396 /**
397 * @param {!WebInspector.AnimationModel.Animation} animation
398 * @return {string}
399 */
400 WebInspector.AnimationUI.Color = function(animation)
401 {
402 var names = Object.keys(WebInspector.AnimationUI.Colors);
403 var color = WebInspector.AnimationUI.Colors[names[String.hashCode(animation. name() || animation.id()) % names.length]];
404 return color.asString(WebInspector.Color.Format.RGB);
405 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698