| Index: Source/devtools/front_end/animation/AnimationTimeline.js
|
| diff --git a/Source/devtools/front_end/animation/AnimationTimeline.js b/Source/devtools/front_end/animation/AnimationTimeline.js
|
| index 1691f8c94fce712e9acc81c2809a3db28ac88741..419b42c9fc8ca32be32e7565ca677199bd6e7499 100644
|
| --- a/Source/devtools/front_end/animation/AnimationTimeline.js
|
| +++ b/Source/devtools/front_end/animation/AnimationTimeline.js
|
| @@ -31,6 +31,10 @@ WebInspector.AnimationTimeline = function()
|
| this._timelineControlsWidth = 230;
|
| /** @type {!Map.<!DOMAgent.BackendNodeId, !WebInspector.AnimationTimeline.NodeUI>} */
|
| this._nodesMap = new Map();
|
| + this._groupBuffer = [];
|
| + this._groupBufferSize = 8;
|
| + /** @type {!Map.<!WebInspector.AnimationModel.AnimationGroup, !WebInspector.AnimationGroupPreviewUI>} */
|
| + this._previewMap = new Map();
|
| this._symbol = Symbol("animationTimeline");
|
| /** @type {!Map.<string, !WebInspector.AnimationModel.Animation>} */
|
| this._animationsMap = new Map();
|
| @@ -81,7 +85,7 @@ WebInspector.AnimationTimeline.prototype = {
|
| {
|
| var animationModel = WebInspector.AnimationModel.fromTarget(target);
|
| animationModel.ensureEnabled();
|
| - animationModel.addEventListener(WebInspector.AnimationModel.Events.AnimationCreated, this._animationCreated, this);
|
| + animationModel.addEventListener(WebInspector.AnimationModel.Events.AnimationGroupStarted, this._animationGroupStarted, this);
|
| animationModel.addEventListener(WebInspector.AnimationModel.Events.AnimationCanceled, this._animationCanceled, this);
|
| },
|
|
|
| @@ -91,7 +95,7 @@ WebInspector.AnimationTimeline.prototype = {
|
| _removeEventListeners: function(target)
|
| {
|
| var animationModel = WebInspector.AnimationModel.fromTarget(target);
|
| - animationModel.removeEventListener(WebInspector.AnimationModel.Events.AnimationCreated, this._animationCreated, this);
|
| + animationModel.removeEventListener(WebInspector.AnimationModel.Events.AnimationGroupStarted, this._animationGroupStarted, this);
|
| animationModel.removeEventListener(WebInspector.AnimationModel.Events.AnimationCanceled, this._animationCanceled, this);
|
| },
|
|
|
| @@ -136,7 +140,7 @@ WebInspector.AnimationTimeline.prototype = {
|
|
|
| var container = createElementWithClass("div", "animation-timeline-header");
|
| var controls = container.createChild("div", "animation-controls");
|
| - container.createChild("div", "animation-timeline-markers");
|
| + this._previewContainer = container.createChild("div", "animation-timeline-buffer");
|
|
|
| var toolbar = new WebInspector.Toolbar(controls);
|
| toolbar.element.classList.add("animation-controls-toolbar");
|
| @@ -334,21 +338,82 @@ WebInspector.AnimationTimeline.prototype = {
|
| delete this._scrubberPlayer;
|
| this._timelineScrubberHead.textContent = WebInspector.UIString(Number.millisToString(0));
|
| this._updateControlButton();
|
| + this._groupBuffer = [];
|
| + this._previewMap.clear();
|
| + this._previewContainer.removeChildren();
|
| },
|
|
|
| /**
|
| * @param {!WebInspector.Event} event
|
| */
|
| - _animationCreated: function(event)
|
| + _animationGroupStarted: function(event)
|
| {
|
| - this._addAnimation(/** @type {!WebInspector.AnimationModel.Animation} */ (event.data.player), event.data.resetTimeline)
|
| + this._addAnimationGroup(/** @type {!WebInspector.AnimationModel.AnimationGroup} */(event.data));
|
| + },
|
| +
|
| + /**
|
| + * @param {!WebInspector.AnimationModel.AnimationGroup} group
|
| + */
|
| + _addAnimationGroup: function(group)
|
| + {
|
| + /**
|
| + * @param {!WebInspector.AnimationModel.AnimationGroup} left
|
| + * @param {!WebInspector.AnimationModel.AnimationGroup} right
|
| + */
|
| + function startTimeComparator(left, right)
|
| + {
|
| + return left.startTime() > right.startTime();
|
| + }
|
| +
|
| + this._groupBuffer.push(group);
|
| + this._groupBuffer.sort(startTimeComparator);
|
| + // Discard oldest groups from buffer if necessary
|
| + var groupsToDiscard = [];
|
| + while (this._groupBuffer.length > this._groupBufferSize) {
|
| + var toDiscard = this._groupBuffer.splice(this._groupBuffer[0] === this._selectedGroup ? 1 : 0, 1);
|
| + groupsToDiscard.push(toDiscard[0]);
|
| + }
|
| + for (var g of groupsToDiscard) {
|
| + this._previewMap.get(g).element.remove();
|
| + this._previewMap.delete(g);
|
| + // TODO(samli): needs to discard model too
|
| + }
|
| + // Generate preview
|
| + var preview = new WebInspector.AnimationGroupPreviewUI(group);
|
| + this._previewMap.set(group, preview);
|
| + this._previewContainer.appendChild(preview.element);
|
| + preview.element.addEventListener("click", this._selectAnimationGroup.bind(this, group));
|
| + },
|
| +
|
| + /**
|
| + * @param {!WebInspector.AnimationModel.AnimationGroup} group
|
| + */
|
| + _selectAnimationGroup: function(group)
|
| + {
|
| + /**
|
| + * @param {!WebInspector.AnimationGroupPreviewUI} ui
|
| + * @param {!WebInspector.AnimationModel.AnimationGroup} group
|
| + * @this {!WebInspector.AnimationTimeline}
|
| + */
|
| + function applySelectionClass(ui, group)
|
| + {
|
| + ui.element.classList.toggle("selected", this._selectedGroup === group);
|
| + }
|
| +
|
| + if (this._selectedGroup === group)
|
| + return;
|
| + this._selectedGroup = group;
|
| + this._previewMap.forEach(applySelectionClass, this);
|
| + this._reset();
|
| + for (var anim of group.animations())
|
| + this._addAnimation(anim);
|
| + this.scheduleRedraw();
|
| },
|
|
|
| /**
|
| * @param {!WebInspector.AnimationModel.Animation} animation
|
| - * @param {boolean} resetTimeline
|
| */
|
| - _addAnimation: function(animation, resetTimeline)
|
| + _addAnimation: function(animation)
|
| {
|
| /**
|
| * @param {?WebInspector.DOMNode} node
|
| @@ -367,15 +432,11 @@ WebInspector.AnimationTimeline.prototype = {
|
| delete this._emptyTimelineMessage;
|
| }
|
|
|
| - if (resetTimeline)
|
| - this._reset();
|
| -
|
| // Ignore Web Animations custom effects & groups
|
| if (animation.type() === "WebAnimation" && animation.source().keyframesRule().keyframes().length === 0)
|
| return;
|
|
|
| - if (this._resizeWindow(animation))
|
| - this.scheduleRedraw();
|
| + this._resizeWindow(animation);
|
|
|
| var nodeUI = this._nodesMap.get(animation.source().backendNodeId());
|
| if (!nodeUI) {
|
| @@ -441,7 +502,7 @@ WebInspector.AnimationTimeline.prototype = {
|
| lastDraw = gridWidth;
|
| var label = this._grid.createSVGChild("text", "animation-timeline-grid-label");
|
| label.setAttribute("x", gridWidth + 5);
|
| - label.setAttribute("y", 35);
|
| + label.setAttribute("y", 15);
|
| label.textContent = WebInspector.UIString(Number.millisToString(time));
|
| }
|
| }
|
| @@ -605,7 +666,8 @@ WebInspector.AnimationTimeline.prototype = {
|
| * @constructor
|
| * @param {!WebInspector.AnimationModel.AnimationEffect} animationEffect
|
| */
|
| -WebInspector.AnimationTimeline.NodeUI = function(animationEffect) {
|
| +WebInspector.AnimationTimeline.NodeUI = function(animationEffect)
|
| +{
|
| /**
|
| * @param {?WebInspector.DOMNode} node
|
| * @this {WebInspector.AnimationTimeline.NodeUI}
|
| @@ -740,7 +802,7 @@ WebInspector.AnimationUI = function(animation, timeline, parentElement) {
|
| this._cachedElements = [];
|
|
|
| this._movementInMs = 0;
|
| - this.redraw();
|
| + this._color = WebInspector.AnimationUI.Color(this._animation);
|
| }
|
|
|
| /**
|
| @@ -780,7 +842,7 @@ WebInspector.AnimationUI.prototype = {
|
| line.setAttribute("x1", WebInspector.AnimationUI.Options.AnimationMargin);
|
| line.setAttribute("y1", WebInspector.AnimationUI.Options.AnimationHeight);
|
| line.setAttribute("y2", WebInspector.AnimationUI.Options.AnimationHeight);
|
| - line.style.stroke = this._color();
|
| + line.style.stroke = this._color;
|
| return line;
|
| },
|
|
|
| @@ -830,11 +892,11 @@ WebInspector.AnimationUI.prototype = {
|
| var circle = parentElement.createSVGChild("circle", keyframeIndex <= 0 ? "animation-endpoint" : "animation-keyframe-point");
|
| circle.setAttribute("cx", x.toFixed(2));
|
| circle.setAttribute("cy", WebInspector.AnimationUI.Options.AnimationHeight);
|
| - circle.style.stroke = this._color();
|
| + circle.style.stroke = this._color;
|
| circle.setAttribute("r", WebInspector.AnimationUI.Options.AnimationMargin / 2);
|
|
|
| if (keyframeIndex <= 0)
|
| - circle.style.fill = this._color();
|
| + circle.style.fill = this._color;
|
|
|
| this._cachedElements[iteration].keyframePoints[keyframeIndex] = circle;
|
|
|
| @@ -883,7 +945,7 @@ WebInspector.AnimationUI.prototype = {
|
| group.style.transform = "translateX(" + leftDistance.toFixed(2) + "px)";
|
|
|
| if (bezier) {
|
| - group.style.fill = this._color();
|
| + group.style.fill = this._color;
|
| WebInspector.BezierUI.drawVelocityChart(bezier, group, width);
|
| } else {
|
| var stepFunction = WebInspector.AnimationTimeline.StepTimingFunction.parse(easing);
|
| @@ -891,7 +953,7 @@ WebInspector.AnimationUI.prototype = {
|
| const offsetMap = {"start": 0, "middle": 0.5, "end": 1};
|
| const offsetWeight = offsetMap[stepFunction.stepAtPosition];
|
| for (var i = 0; i < stepFunction.steps; i++)
|
| - createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, this._color());
|
| + createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, this._color);
|
| }
|
| },
|
|
|
| @@ -1050,7 +1112,8 @@ WebInspector.AnimationUI.prototype = {
|
| this._setDelay(delay);
|
| this._setDuration(duration);
|
| if (this._animation.type() !== "CSSAnimation") {
|
| - for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page))
|
| + var target = WebInspector.targetManager.mainTarget();
|
| + if (target)
|
| target.animationAgent().setTiming(this._animation.id(), duration, delay);
|
| }
|
| }
|
| @@ -1116,31 +1179,6 @@ WebInspector.AnimationUI.prototype = {
|
| style = style.replace(new RegExp("\\s*(-webkit-)?" + name + ":[^;]*;?\\s*", "g"), "");
|
| var valueString = name + ": " + value;
|
| this._node.setAttributeValue("style", style + " " + valueString + "; -webkit-" + valueString + ";");
|
| - },
|
| -
|
| - /**
|
| - * @return {string}
|
| - */
|
| - _color: function()
|
| - {
|
| - /**
|
| - * @param {string} string
|
| - * @return {number}
|
| - */
|
| - function hash(string)
|
| - {
|
| - var hash = 0;
|
| - for (var i = 0; i < string.length; i++)
|
| - hash = (hash << 5) + hash + string.charCodeAt(i);
|
| - return Math.abs(hash);
|
| - }
|
| -
|
| - if (!this._selectedColor) {
|
| - var names = Object.keys(WebInspector.AnimationUI.Colors);
|
| - var color = WebInspector.AnimationUI.Colors[names[hash(this._animation.name() || this._animation.id()) % names.length]];
|
| - this._selectedColor = color.asString(WebInspector.Color.Format.RGB);
|
| - }
|
| - return this._selectedColor;
|
| }
|
| }
|
|
|
| @@ -1158,8 +1196,33 @@ WebInspector.AnimationUI.Colors = {
|
| "Deep Orange": WebInspector.Color.parse("#FF5722"),
|
| "Blue": WebInspector.Color.parse("#5677FC"),
|
| "Lime": WebInspector.Color.parse("#CDDC39"),
|
| + "Blue Grey": WebInspector.Color.parse("#607D8B"),
|
| "Pink": WebInspector.Color.parse("#E91E63"),
|
| "Green": WebInspector.Color.parse("#0F9D58"),
|
| "Brown": WebInspector.Color.parse("#795548"),
|
| "Cyan": WebInspector.Color.parse("#00BCD4")
|
| }
|
| +
|
| +
|
| +/**
|
| + * @param {!WebInspector.AnimationModel.Animation} animation
|
| + * @return {string}
|
| + */
|
| +WebInspector.AnimationUI.Color = function(animation)
|
| +{
|
| + /**
|
| + * @param {string} string
|
| + * @return {number}
|
| + */
|
| + function hash(string)
|
| + {
|
| + var hash = 0;
|
| + for (var i = 0; i < string.length; i++)
|
| + hash = (hash << 5) + hash + string.charCodeAt(i);
|
| + return Math.abs(hash);
|
| + }
|
| +
|
| + var names = Object.keys(WebInspector.AnimationUI.Colors);
|
| + var color = WebInspector.AnimationUI.Colors[names[hash(animation.name() || animation.id()) % names.length]];
|
| + return color.asString(WebInspector.Color.Format.RGB);
|
| +}
|
|
|