| Index: third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js
|
| diff --git a/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js b/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js
|
| index f6609e760e3c36fe496aef2214d70ff2a48ea703..9b2abe39b9e482be11b23eb68fca14264a1b0868 100644
|
| --- a/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js
|
| +++ b/third_party/WebKit/Source/devtools/front_end/animation/AnimationUI.js
|
| @@ -1,405 +1,416 @@
|
| // Copyright (c) 2015 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
| -
|
| /**
|
| - * @constructor
|
| - * @param {!WebInspector.AnimationModel.Animation} animation
|
| - * @param {!WebInspector.AnimationTimeline} timeline
|
| - * @param {!Element} parentElement
|
| + * @unrestricted
|
| */
|
| -WebInspector.AnimationUI = function(animation, timeline, parentElement) {
|
| +WebInspector.AnimationUI = class {
|
| + /**
|
| + * @param {!WebInspector.AnimationModel.Animation} animation
|
| + * @param {!WebInspector.AnimationTimeline} timeline
|
| + * @param {!Element} parentElement
|
| + */
|
| + constructor(animation, timeline, parentElement) {
|
| this._animation = animation;
|
| this._timeline = timeline;
|
| this._parentElement = parentElement;
|
|
|
| if (this._animation.source().keyframesRule())
|
| - this._keyframes = this._animation.source().keyframesRule().keyframes();
|
| + this._keyframes = this._animation.source().keyframesRule().keyframes();
|
|
|
| - this._nameElement = parentElement.createChild("div", "animation-name");
|
| + this._nameElement = parentElement.createChild('div', 'animation-name');
|
| this._nameElement.textContent = this._animation.name();
|
|
|
| - this._svg = parentElement.createSVGChild("svg", "animation-ui");
|
| - this._svg.setAttribute("height", WebInspector.AnimationUI.Options.AnimationSVGHeight);
|
| - this._svg.style.marginLeft = "-" + WebInspector.AnimationUI.Options.AnimationMargin + "px";
|
| - this._svg.addEventListener("contextmenu", this._onContextMenu.bind(this));
|
| - this._activeIntervalGroup = this._svg.createSVGChild("g");
|
| - WebInspector.installDragHandle(this._activeIntervalGroup, this._mouseDown.bind(this, WebInspector.AnimationUI.MouseEvents.AnimationDrag, null), this._mouseMove.bind(this), this._mouseUp.bind(this), "-webkit-grabbing", "-webkit-grab");
|
| + this._svg = parentElement.createSVGChild('svg', 'animation-ui');
|
| + this._svg.setAttribute('height', WebInspector.AnimationUI.Options.AnimationSVGHeight);
|
| + this._svg.style.marginLeft = '-' + WebInspector.AnimationUI.Options.AnimationMargin + 'px';
|
| + this._svg.addEventListener('contextmenu', this._onContextMenu.bind(this));
|
| + this._activeIntervalGroup = this._svg.createSVGChild('g');
|
| + WebInspector.installDragHandle(
|
| + this._activeIntervalGroup, this._mouseDown.bind(this, WebInspector.AnimationUI.MouseEvents.AnimationDrag, null),
|
| + this._mouseMove.bind(this), this._mouseUp.bind(this), '-webkit-grabbing', '-webkit-grab');
|
|
|
| /** @type {!Array.<{group: ?Element, animationLine: ?Element, keyframePoints: !Object.<number, !Element>, keyframeRender: !Object.<number, !Element>}>} */
|
| this._cachedElements = [];
|
|
|
| this._movementInMs = 0;
|
| this._color = WebInspector.AnimationUI.Color(this._animation);
|
| -};
|
| -
|
| -/**
|
| - * @enum {string}
|
| - */
|
| -WebInspector.AnimationUI.MouseEvents = {
|
| - AnimationDrag: "AnimationDrag",
|
| - KeyframeMove: "KeyframeMove",
|
| - StartEndpointMove: "StartEndpointMove",
|
| - FinishEndpointMove: "FinishEndpointMove"
|
| -};
|
| -
|
| -WebInspector.AnimationUI.prototype = {
|
| - /**
|
| - * @return {!WebInspector.AnimationModel.Animation}
|
| - */
|
| - animation: function()
|
| - {
|
| - return this._animation;
|
| - },
|
| -
|
| - /**
|
| - * @param {?WebInspector.DOMNode} node
|
| - */
|
| - setNode: function(node)
|
| - {
|
| - this._node = node;
|
| - },
|
| -
|
| - /**
|
| - * @param {!Element} parentElement
|
| - * @param {string} className
|
| - */
|
| - _createLine: function(parentElement, className)
|
| - {
|
| - var line = parentElement.createSVGChild("line", className);
|
| - 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;
|
| - return line;
|
| - },
|
| + }
|
|
|
| - /**
|
| - * @param {number} iteration
|
| - * @param {!Element} parentElement
|
| - */
|
| - _drawAnimationLine: function(iteration, parentElement)
|
| - {
|
| - var cache = this._cachedElements[iteration];
|
| - if (!cache.animationLine)
|
| - cache.animationLine = this._createLine(parentElement, "animation-line");
|
| - cache.animationLine.setAttribute("x2", (this._duration() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2));
|
| - },
|
| -
|
| - /**
|
| - * @param {!Element} parentElement
|
| - */
|
| - _drawDelayLine: function(parentElement)
|
| - {
|
| - if (!this._delayLine) {
|
| - this._delayLine = this._createLine(parentElement, "animation-delay-line");
|
| - this._endDelayLine = this._createLine(parentElement, "animation-delay-line");
|
| - }
|
| - var fill = this._animation.source().fill();
|
| - this._delayLine.classList.toggle("animation-fill", fill === "backwards" || fill === "both");
|
| - var margin = WebInspector.AnimationUI.Options.AnimationMargin;
|
| - this._delayLine.setAttribute("x1", margin);
|
| - this._delayLine.setAttribute("x2", (this._delay() * this._timeline.pixelMsRatio() + margin).toFixed(2));
|
| - var forwardsFill = fill === "forwards" || fill === "both";
|
| - this._endDelayLine.classList.toggle("animation-fill", forwardsFill);
|
| - var leftMargin = Math.min(this._timeline.width(), (this._delay() + this._duration() * this._animation.source().iterations()) * this._timeline.pixelMsRatio());
|
| - this._endDelayLine.style.transform = "translateX(" + leftMargin.toFixed(2) + "px)";
|
| - this._endDelayLine.setAttribute("x1", margin);
|
| - this._endDelayLine.setAttribute("x2", forwardsFill
|
| - ? (this._timeline.width() - leftMargin + margin).toFixed(2)
|
| - : (this._animation.source().endDelay() * this._timeline.pixelMsRatio() + margin).toFixed(2));
|
| - },
|
| + /**
|
| + * @param {!WebInspector.AnimationModel.Animation} animation
|
| + * @return {string}
|
| + */
|
| + static Color(animation) {
|
| + var names = Object.keys(WebInspector.AnimationUI.Colors);
|
| + var color =
|
| + WebInspector.AnimationUI.Colors[names[String.hashCode(animation.name() || animation.id()) % names.length]];
|
| + return color.asString(WebInspector.Color.Format.RGB);
|
| + }
|
| +
|
| + /**
|
| + * @return {!WebInspector.AnimationModel.Animation}
|
| + */
|
| + animation() {
|
| + return this._animation;
|
| + }
|
| +
|
| + /**
|
| + * @param {?WebInspector.DOMNode} node
|
| + */
|
| + setNode(node) {
|
| + this._node = node;
|
| + }
|
| +
|
| + /**
|
| + * @param {!Element} parentElement
|
| + * @param {string} className
|
| + */
|
| + _createLine(parentElement, className) {
|
| + var line = parentElement.createSVGChild('line', className);
|
| + 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;
|
| + return line;
|
| + }
|
| +
|
| + /**
|
| + * @param {number} iteration
|
| + * @param {!Element} parentElement
|
| + */
|
| + _drawAnimationLine(iteration, parentElement) {
|
| + var cache = this._cachedElements[iteration];
|
| + if (!cache.animationLine)
|
| + cache.animationLine = this._createLine(parentElement, 'animation-line');
|
| + cache.animationLine.setAttribute(
|
| + 'x2', (this._duration() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin)
|
| + .toFixed(2));
|
| + }
|
| +
|
| + /**
|
| + * @param {!Element} parentElement
|
| + */
|
| + _drawDelayLine(parentElement) {
|
| + if (!this._delayLine) {
|
| + this._delayLine = this._createLine(parentElement, 'animation-delay-line');
|
| + this._endDelayLine = this._createLine(parentElement, 'animation-delay-line');
|
| + }
|
| + var fill = this._animation.source().fill();
|
| + this._delayLine.classList.toggle('animation-fill', fill === 'backwards' || fill === 'both');
|
| + var margin = WebInspector.AnimationUI.Options.AnimationMargin;
|
| + this._delayLine.setAttribute('x1', margin);
|
| + this._delayLine.setAttribute('x2', (this._delay() * this._timeline.pixelMsRatio() + margin).toFixed(2));
|
| + var forwardsFill = fill === 'forwards' || fill === 'both';
|
| + this._endDelayLine.classList.toggle('animation-fill', forwardsFill);
|
| + var leftMargin = Math.min(
|
| + this._timeline.width(),
|
| + (this._delay() + this._duration() * this._animation.source().iterations()) * this._timeline.pixelMsRatio());
|
| + this._endDelayLine.style.transform = 'translateX(' + leftMargin.toFixed(2) + 'px)';
|
| + this._endDelayLine.setAttribute('x1', margin);
|
| + this._endDelayLine.setAttribute(
|
| + 'x2', forwardsFill ? (this._timeline.width() - leftMargin + margin).toFixed(2) :
|
| + (this._animation.source().endDelay() * this._timeline.pixelMsRatio() + margin).toFixed(2));
|
| + }
|
| +
|
| + /**
|
| + * @param {number} iteration
|
| + * @param {!Element} parentElement
|
| + * @param {number} x
|
| + * @param {number} keyframeIndex
|
| + * @param {boolean} attachEvents
|
| + */
|
| + _drawPoint(iteration, parentElement, x, keyframeIndex, attachEvents) {
|
| + if (this._cachedElements[iteration].keyframePoints[keyframeIndex]) {
|
| + this._cachedElements[iteration].keyframePoints[keyframeIndex].setAttribute('cx', x.toFixed(2));
|
| + return;
|
| + }
|
|
|
| + 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.setAttribute('r', WebInspector.AnimationUI.Options.AnimationMargin / 2);
|
| +
|
| + if (keyframeIndex <= 0)
|
| + circle.style.fill = this._color;
|
| +
|
| + this._cachedElements[iteration].keyframePoints[keyframeIndex] = circle;
|
| +
|
| + if (!attachEvents)
|
| + return;
|
| +
|
| + var eventType;
|
| + if (keyframeIndex === 0)
|
| + eventType = WebInspector.AnimationUI.MouseEvents.StartEndpointMove;
|
| + else if (keyframeIndex === -1)
|
| + eventType = WebInspector.AnimationUI.MouseEvents.FinishEndpointMove;
|
| + else
|
| + eventType = WebInspector.AnimationUI.MouseEvents.KeyframeMove;
|
| + WebInspector.installDragHandle(
|
| + circle, this._mouseDown.bind(this, eventType, keyframeIndex), this._mouseMove.bind(this),
|
| + this._mouseUp.bind(this), 'ew-resize');
|
| + }
|
| +
|
| + /**
|
| + * @param {number} iteration
|
| + * @param {number} keyframeIndex
|
| + * @param {!Element} parentElement
|
| + * @param {number} leftDistance
|
| + * @param {number} width
|
| + * @param {string} easing
|
| + */
|
| + _renderKeyframe(iteration, keyframeIndex, parentElement, leftDistance, width, easing) {
|
| /**
|
| - * @param {number} iteration
|
| * @param {!Element} parentElement
|
| * @param {number} x
|
| - * @param {number} keyframeIndex
|
| - * @param {boolean} attachEvents
|
| + * @param {string} strokeColor
|
| */
|
| - _drawPoint: function(iteration, parentElement, x, keyframeIndex, attachEvents)
|
| - {
|
| - if (this._cachedElements[iteration].keyframePoints[keyframeIndex]) {
|
| - this._cachedElements[iteration].keyframePoints[keyframeIndex].setAttribute("cx", x.toFixed(2));
|
| - return;
|
| - }
|
| -
|
| - 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.setAttribute("r", WebInspector.AnimationUI.Options.AnimationMargin / 2);
|
| -
|
| - if (keyframeIndex <= 0)
|
| - circle.style.fill = this._color;
|
| -
|
| - this._cachedElements[iteration].keyframePoints[keyframeIndex] = circle;
|
| -
|
| - if (!attachEvents)
|
| - return;
|
| -
|
| - var eventType;
|
| - if (keyframeIndex === 0)
|
| - eventType = WebInspector.AnimationUI.MouseEvents.StartEndpointMove;
|
| - else if (keyframeIndex === -1)
|
| - eventType = WebInspector.AnimationUI.MouseEvents.FinishEndpointMove;
|
| - else
|
| - eventType = WebInspector.AnimationUI.MouseEvents.KeyframeMove;
|
| - WebInspector.installDragHandle(circle, this._mouseDown.bind(this, eventType, keyframeIndex), this._mouseMove.bind(this), this._mouseUp.bind(this), "ew-resize");
|
| - },
|
| -
|
| - /**
|
| - * @param {number} iteration
|
| - * @param {number} keyframeIndex
|
| - * @param {!Element} parentElement
|
| - * @param {number} leftDistance
|
| - * @param {number} width
|
| - * @param {string} easing
|
| - */
|
| - _renderKeyframe: function(iteration, keyframeIndex, parentElement, leftDistance, width, easing)
|
| - {
|
| - /**
|
| - * @param {!Element} parentElement
|
| - * @param {number} x
|
| - * @param {string} strokeColor
|
| - */
|
| - function createStepLine(parentElement, x, strokeColor)
|
| - {
|
| - var line = parentElement.createSVGChild("line");
|
| - line.setAttribute("x1", x);
|
| - line.setAttribute("x2", x);
|
| - line.setAttribute("y1", WebInspector.AnimationUI.Options.AnimationMargin);
|
| - line.setAttribute("y2", WebInspector.AnimationUI.Options.AnimationHeight);
|
| - line.style.stroke = strokeColor;
|
| - }
|
| -
|
| - var bezier = WebInspector.Geometry.CubicBezier.parse(easing);
|
| - var cache = this._cachedElements[iteration].keyframeRender;
|
| - if (!cache[keyframeIndex])
|
| - cache[keyframeIndex] = bezier ? parentElement.createSVGChild("path", "animation-keyframe") : parentElement.createSVGChild("g", "animation-keyframe-step");
|
| - var group = cache[keyframeIndex];
|
| - group.style.transform = "translateX(" + leftDistance.toFixed(2) + "px)";
|
| -
|
| - if (easing === "linear") {
|
| - group.style.fill = this._color;
|
| - var height = WebInspector.BezierUI.Height;
|
| - group.setAttribute("d", ["M", 0, height, "L", 0, 5, "L", width.toFixed(2), 5, "L", width.toFixed(2), height, "Z"].join(" "));
|
| - } else if (bezier) {
|
| - group.style.fill = this._color;
|
| - WebInspector.BezierUI.drawVelocityChart(bezier, group, width);
|
| - } else {
|
| - var stepFunction = WebInspector.AnimationTimeline.StepTimingFunction.parse(easing);
|
| - group.removeChildren();
|
| - /** @const */ var offsetMap = {"start": 0, "middle": 0.5, "end": 1};
|
| - /** @const */ var offsetWeight = offsetMap[stepFunction.stepAtPosition];
|
| - for (var i = 0; i < stepFunction.steps; i++)
|
| - createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, this._color);
|
| - }
|
| - },
|
| -
|
| - redraw: function()
|
| - {
|
| - var durationWithDelay = this._delay() + this._duration() * this._animation.source().iterations() + this._animation.source().endDelay();
|
| - var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options.AnimationMargin;
|
| -
|
| - this._svg.setAttribute("width", (maxWidth + 2 * WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2));
|
| - this._activeIntervalGroup.style.transform = "translateX(" + (this._delay() * this._timeline.pixelMsRatio()).toFixed(2) + "px)";
|
| -
|
| - this._nameElement.style.transform = "translateX(" + (this._delay() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2) + "px)";
|
| - this._nameElement.style.width = (this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + "px";
|
| - this._drawDelayLine(this._svg);
|
| -
|
| - if (this._animation.type() === "CSSTransition") {
|
| - this._renderTransition();
|
| - return;
|
| - }
|
| -
|
| - this._renderIteration(this._activeIntervalGroup, 0);
|
| - if (!this._tailGroup)
|
| - this._tailGroup = this._activeIntervalGroup.createSVGChild("g", "animation-tail-iterations");
|
| - var iterationWidth = this._duration() * this._timeline.pixelMsRatio();
|
| - for (var iteration = 1; iteration < this._animation.source().iterations() && iterationWidth * (iteration - 1) < this._timeline.width(); iteration++)
|
| - this._renderIteration(this._tailGroup, iteration);
|
| - while (iteration < this._cachedElements.length)
|
| - this._cachedElements.pop().group.remove();
|
| - },
|
| -
|
| -
|
| - _renderTransition: function()
|
| - {
|
| - if (!this._cachedElements[0])
|
| - this._cachedElements[0] = { animationLine: null, keyframePoints: {}, keyframeRender: {}, group: null };
|
| - this._drawAnimationLine(0, this._activeIntervalGroup);
|
| - this._renderKeyframe(0, 0, this._activeIntervalGroup, WebInspector.AnimationUI.Options.AnimationMargin, this._duration() * this._timeline.pixelMsRatio(), this._animation.source().easing());
|
| - this._drawPoint(0, this._activeIntervalGroup, WebInspector.AnimationUI.Options.AnimationMargin, 0, true);
|
| - this._drawPoint(0, this._activeIntervalGroup, this._duration() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1, true);
|
| - },
|
| -
|
| - /**
|
| - * @param {!Element} parentElement
|
| - * @param {number} iteration
|
| - */
|
| - _renderIteration: function(parentElement, iteration)
|
| - {
|
| - if (!this._cachedElements[iteration])
|
| - this._cachedElements[iteration] = { animationLine: null, keyframePoints: {}, keyframeRender: {}, group: parentElement.createSVGChild("g") };
|
| - var group = this._cachedElements[iteration].group;
|
| - group.style.transform = "translateX(" + (iteration * this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + "px)";
|
| - this._drawAnimationLine(iteration, group);
|
| - console.assert(this._keyframes.length > 1);
|
| - for (var i = 0; i < this._keyframes.length - 1; i++) {
|
| - var leftDistance = this._offset(i) * this._duration() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin;
|
| - var width = this._duration() * (this._offset(i + 1) - this._offset(i)) * this._timeline.pixelMsRatio();
|
| - this._renderKeyframe(iteration, i, group, leftDistance, width, this._keyframes[i].easing());
|
| - if (i || (!i && iteration === 0))
|
| - this._drawPoint(iteration, group, leftDistance, i, iteration === 0);
|
| - }
|
| - this._drawPoint(iteration, group, this._duration() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1, iteration === 0);
|
| - },
|
| -
|
| - /**
|
| - * @return {number}
|
| - */
|
| - _delay: function()
|
| - {
|
| - var delay = this._animation.source().delay();
|
| - if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.AnimationDrag || this._mouseEventType === WebInspector.AnimationUI.MouseEvents.StartEndpointMove)
|
| - delay += this._movementInMs;
|
| - // FIXME: add support for negative start delay
|
| - return Math.max(0, delay);
|
| - },
|
| + function createStepLine(parentElement, x, strokeColor) {
|
| + var line = parentElement.createSVGChild('line');
|
| + line.setAttribute('x1', x);
|
| + line.setAttribute('x2', x);
|
| + line.setAttribute('y1', WebInspector.AnimationUI.Options.AnimationMargin);
|
| + line.setAttribute('y2', WebInspector.AnimationUI.Options.AnimationHeight);
|
| + line.style.stroke = strokeColor;
|
| + }
|
|
|
| - /**
|
| - * @return {number}
|
| - */
|
| - _duration: function()
|
| - {
|
| - var duration = this._animation.source().duration();
|
| - if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.FinishEndpointMove)
|
| - duration += this._movementInMs;
|
| - else if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.StartEndpointMove)
|
| - duration -= Math.max(this._movementInMs, -this._animation.source().delay()); // Cannot have negative delay
|
| - return Math.max(0, duration);
|
| - },
|
| + var bezier = WebInspector.Geometry.CubicBezier.parse(easing);
|
| + var cache = this._cachedElements[iteration].keyframeRender;
|
| + if (!cache[keyframeIndex])
|
| + cache[keyframeIndex] = bezier ? parentElement.createSVGChild('path', 'animation-keyframe') :
|
| + parentElement.createSVGChild('g', 'animation-keyframe-step');
|
| + var group = cache[keyframeIndex];
|
| + group.style.transform = 'translateX(' + leftDistance.toFixed(2) + 'px)';
|
| +
|
| + if (easing === 'linear') {
|
| + group.style.fill = this._color;
|
| + var height = WebInspector.BezierUI.Height;
|
| + group.setAttribute(
|
| + 'd', ['M', 0, height, 'L', 0, 5, 'L', width.toFixed(2), 5, 'L', width.toFixed(2), height, 'Z'].join(' '));
|
| + } else if (bezier) {
|
| + group.style.fill = this._color;
|
| + WebInspector.BezierUI.drawVelocityChart(bezier, group, width);
|
| + } else {
|
| + var stepFunction = WebInspector.AnimationTimeline.StepTimingFunction.parse(easing);
|
| + group.removeChildren();
|
| + /** @const */ var offsetMap = {'start': 0, 'middle': 0.5, 'end': 1};
|
| + /** @const */ var offsetWeight = offsetMap[stepFunction.stepAtPosition];
|
| + for (var i = 0; i < stepFunction.steps; i++)
|
| + createStepLine(group, (i + offsetWeight) * width / stepFunction.steps, this._color);
|
| + }
|
| + }
|
| +
|
| + redraw() {
|
| + var durationWithDelay =
|
| + this._delay() + this._duration() * this._animation.source().iterations() + this._animation.source().endDelay();
|
| + var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options.AnimationMargin;
|
| +
|
| + this._svg.setAttribute('width', (maxWidth + 2 * WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2));
|
| + this._activeIntervalGroup.style.transform =
|
| + 'translateX(' + (this._delay() * this._timeline.pixelMsRatio()).toFixed(2) + 'px)';
|
| +
|
| + this._nameElement.style.transform = 'translateX(' +
|
| + (this._delay() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2) +
|
| + 'px)';
|
| + this._nameElement.style.width = (this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + 'px';
|
| + this._drawDelayLine(this._svg);
|
| +
|
| + if (this._animation.type() === 'CSSTransition') {
|
| + this._renderTransition();
|
| + return;
|
| + }
|
|
|
| - /**
|
| - * @param {number} i
|
| - * @return {number} offset
|
| - */
|
| - _offset: function(i)
|
| - {
|
| - var offset = this._keyframes[i].offsetAsNumber();
|
| - if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.KeyframeMove && i === this._keyframeMoved) {
|
| - console.assert(i > 0 && i < this._keyframes.length - 1, "First and last keyframe cannot be moved");
|
| - offset += this._movementInMs / this._animation.source().duration();
|
| - offset = Math.max(offset, this._keyframes[i - 1].offsetAsNumber());
|
| - offset = Math.min(offset, this._keyframes[i + 1].offsetAsNumber());
|
| - }
|
| - return offset;
|
| - },
|
| + this._renderIteration(this._activeIntervalGroup, 0);
|
| + if (!this._tailGroup)
|
| + this._tailGroup = this._activeIntervalGroup.createSVGChild('g', 'animation-tail-iterations');
|
| + var iterationWidth = this._duration() * this._timeline.pixelMsRatio();
|
| + for (var iteration = 1;
|
| + iteration < this._animation.source().iterations() && iterationWidth * (iteration - 1) < this._timeline.width();
|
| + iteration++)
|
| + this._renderIteration(this._tailGroup, iteration);
|
| + while (iteration < this._cachedElements.length)
|
| + this._cachedElements.pop().group.remove();
|
| + }
|
| +
|
| + _renderTransition() {
|
| + if (!this._cachedElements[0])
|
| + this._cachedElements[0] = {animationLine: null, keyframePoints: {}, keyframeRender: {}, group: null};
|
| + this._drawAnimationLine(0, this._activeIntervalGroup);
|
| + this._renderKeyframe(
|
| + 0, 0, this._activeIntervalGroup, WebInspector.AnimationUI.Options.AnimationMargin,
|
| + this._duration() * this._timeline.pixelMsRatio(), this._animation.source().easing());
|
| + this._drawPoint(0, this._activeIntervalGroup, WebInspector.AnimationUI.Options.AnimationMargin, 0, true);
|
| + this._drawPoint(
|
| + 0, this._activeIntervalGroup,
|
| + this._duration() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1, true);
|
| + }
|
| +
|
| + /**
|
| + * @param {!Element} parentElement
|
| + * @param {number} iteration
|
| + */
|
| + _renderIteration(parentElement, iteration) {
|
| + if (!this._cachedElements[iteration])
|
| + this._cachedElements[iteration] =
|
| + {animationLine: null, keyframePoints: {}, keyframeRender: {}, group: parentElement.createSVGChild('g')};
|
| + var group = this._cachedElements[iteration].group;
|
| + group.style.transform =
|
| + 'translateX(' + (iteration * this._duration() * this._timeline.pixelMsRatio()).toFixed(2) + 'px)';
|
| + this._drawAnimationLine(iteration, group);
|
| + console.assert(this._keyframes.length > 1);
|
| + for (var i = 0; i < this._keyframes.length - 1; i++) {
|
| + var leftDistance = this._offset(i) * this._duration() * this._timeline.pixelMsRatio() +
|
| + WebInspector.AnimationUI.Options.AnimationMargin;
|
| + var width = this._duration() * (this._offset(i + 1) - this._offset(i)) * this._timeline.pixelMsRatio();
|
| + this._renderKeyframe(iteration, i, group, leftDistance, width, this._keyframes[i].easing());
|
| + if (i || (!i && iteration === 0))
|
| + this._drawPoint(iteration, group, leftDistance, i, iteration === 0);
|
| + }
|
| + this._drawPoint(
|
| + iteration, group,
|
| + this._duration() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1,
|
| + iteration === 0);
|
| + }
|
| +
|
| + /**
|
| + * @return {number}
|
| + */
|
| + _delay() {
|
| + var delay = this._animation.source().delay();
|
| + if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.AnimationDrag ||
|
| + this._mouseEventType === WebInspector.AnimationUI.MouseEvents.StartEndpointMove)
|
| + delay += this._movementInMs;
|
| + // FIXME: add support for negative start delay
|
| + return Math.max(0, delay);
|
| + }
|
| +
|
| + /**
|
| + * @return {number}
|
| + */
|
| + _duration() {
|
| + var duration = this._animation.source().duration();
|
| + if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.FinishEndpointMove)
|
| + duration += this._movementInMs;
|
| + else if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.StartEndpointMove)
|
| + duration -= Math.max(this._movementInMs, -this._animation.source().delay()); // Cannot have negative delay
|
| + return Math.max(0, duration);
|
| + }
|
| +
|
| + /**
|
| + * @param {number} i
|
| + * @return {number} offset
|
| + */
|
| + _offset(i) {
|
| + var offset = this._keyframes[i].offsetAsNumber();
|
| + if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.KeyframeMove && i === this._keyframeMoved) {
|
| + console.assert(i > 0 && i < this._keyframes.length - 1, 'First and last keyframe cannot be moved');
|
| + offset += this._movementInMs / this._animation.source().duration();
|
| + offset = Math.max(offset, this._keyframes[i - 1].offsetAsNumber());
|
| + offset = Math.min(offset, this._keyframes[i + 1].offsetAsNumber());
|
| + }
|
| + return offset;
|
| + }
|
| +
|
| + /**
|
| + * @param {!WebInspector.AnimationUI.MouseEvents} mouseEventType
|
| + * @param {?number} keyframeIndex
|
| + * @param {!Event} event
|
| + */
|
| + _mouseDown(mouseEventType, keyframeIndex, event) {
|
| + if (event.buttons === 2)
|
| + return false;
|
| + if (this._svg.enclosingNodeOrSelfWithClass('animation-node-removed'))
|
| + return false;
|
| + this._mouseEventType = mouseEventType;
|
| + this._keyframeMoved = keyframeIndex;
|
| + this._downMouseX = event.clientX;
|
| + event.consume(true);
|
| + if (this._node)
|
| + WebInspector.Revealer.reveal(this._node);
|
| + return true;
|
| + }
|
| +
|
| + /**
|
| + * @param {!Event} event
|
| + */
|
| + _mouseMove(event) {
|
| + this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio();
|
| + if (this._delay() + this._duration() > this._timeline.duration() * 0.8)
|
| + this._timeline.setDuration(this._timeline.duration() * 1.2);
|
| + this.redraw();
|
| + }
|
| +
|
| + /**
|
| + * @param {!Event} event
|
| + */
|
| + _mouseUp(event) {
|
| + this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio();
|
| +
|
| + // Commit changes
|
| + if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.KeyframeMove)
|
| + this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframeMoved));
|
| + else
|
| + this._animation.setTiming(this._duration(), this._delay());
|
|
|
| - /**
|
| - * @param {!WebInspector.AnimationUI.MouseEvents} mouseEventType
|
| - * @param {?number} keyframeIndex
|
| - * @param {!Event} event
|
| - */
|
| - _mouseDown: function(mouseEventType, keyframeIndex, event)
|
| - {
|
| - if (event.buttons === 2)
|
| - return false;
|
| - if (this._svg.enclosingNodeOrSelfWithClass("animation-node-removed"))
|
| - return false;
|
| - this._mouseEventType = mouseEventType;
|
| - this._keyframeMoved = keyframeIndex;
|
| - this._downMouseX = event.clientX;
|
| - event.consume(true);
|
| - if (this._node)
|
| - WebInspector.Revealer.reveal(this._node);
|
| - return true;
|
| - },
|
| + this._movementInMs = 0;
|
| + this.redraw();
|
|
|
| - /**
|
| - * @param {!Event} event
|
| - */
|
| - _mouseMove: function(event)
|
| - {
|
| - this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio();
|
| - if (this._delay() + this._duration() > this._timeline.duration() * 0.8)
|
| - this._timeline.setDuration(this._timeline.duration() * 1.2);
|
| - this.redraw();
|
| - },
|
| + delete this._mouseEventType;
|
| + delete this._downMouseX;
|
| + delete this._keyframeMoved;
|
| + }
|
|
|
| + /**
|
| + * @param {!Event} event
|
| + */
|
| + _onContextMenu(event) {
|
| /**
|
| - * @param {!Event} event
|
| + * @param {?WebInspector.RemoteObject} remoteObject
|
| */
|
| - _mouseUp: function(event)
|
| - {
|
| - this._movementInMs = (event.clientX - this._downMouseX) / this._timeline.pixelMsRatio();
|
| -
|
| - // Commit changes
|
| - if (this._mouseEventType === WebInspector.AnimationUI.MouseEvents.KeyframeMove)
|
| - this._keyframes[this._keyframeMoved].setOffset(this._offset(this._keyframeMoved));
|
| - else
|
| - this._animation.setTiming(this._duration(), this._delay());
|
| -
|
| - this._movementInMs = 0;
|
| - this.redraw();
|
| + function showContextMenu(remoteObject) {
|
| + if (!remoteObject)
|
| + return;
|
| + var contextMenu = new WebInspector.ContextMenu(event);
|
| + contextMenu.appendApplicableItems(remoteObject);
|
| + contextMenu.show();
|
| + }
|
|
|
| - delete this._mouseEventType;
|
| - delete this._downMouseX;
|
| - delete this._keyframeMoved;
|
| - },
|
| + this._animation.remoteObjectPromise().then(showContextMenu);
|
| + event.consume(true);
|
| + }
|
| +};
|
|
|
| - /**
|
| - * @param {!Event} event
|
| - */
|
| - _onContextMenu: function(event)
|
| - {
|
| - /**
|
| - * @param {?WebInspector.RemoteObject} remoteObject
|
| - */
|
| - function showContextMenu(remoteObject)
|
| - {
|
| - if (!remoteObject)
|
| - return;
|
| - var contextMenu = new WebInspector.ContextMenu(event);
|
| - contextMenu.appendApplicableItems(remoteObject);
|
| - contextMenu.show();
|
| - }
|
| -
|
| - this._animation.remoteObjectPromise().then(showContextMenu);
|
| - event.consume(true);
|
| - }
|
| +/**
|
| + * @enum {string}
|
| + */
|
| +WebInspector.AnimationUI.MouseEvents = {
|
| + AnimationDrag: 'AnimationDrag',
|
| + KeyframeMove: 'KeyframeMove',
|
| + StartEndpointMove: 'StartEndpointMove',
|
| + FinishEndpointMove: 'FinishEndpointMove'
|
| };
|
|
|
| WebInspector.AnimationUI.Options = {
|
| - AnimationHeight: 26,
|
| - AnimationSVGHeight: 50,
|
| - AnimationMargin: 7,
|
| - EndpointsClickRegionSize: 10,
|
| - GridCanvasHeight: 40
|
| + AnimationHeight: 26,
|
| + AnimationSVGHeight: 50,
|
| + AnimationMargin: 7,
|
| + EndpointsClickRegionSize: 10,
|
| + GridCanvasHeight: 40
|
| };
|
|
|
| WebInspector.AnimationUI.Colors = {
|
| - "Purple": WebInspector.Color.parse("#9C27B0"),
|
| - "Light Blue": WebInspector.Color.parse("#03A9F4"),
|
| - "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")
|
| + 'Purple': WebInspector.Color.parse('#9C27B0'),
|
| + 'Light Blue': WebInspector.Color.parse('#03A9F4'),
|
| + '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)
|
| -{
|
| - var names = Object.keys(WebInspector.AnimationUI.Colors);
|
| - var color = WebInspector.AnimationUI.Colors[names[String.hashCode(animation.name() || animation.id()) % names.length]];
|
| - return color.asString(WebInspector.Color.Format.RGB);
|
| -};
|
| +
|
|
|