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

Side by Side Diff: Source/devtools/front_end/elements/AnimationTimeline.js

Issue 1155773002: Devtools Animations: Add cubic bezier easing editor for animations (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Remove empty line Created 5 years, 7 months 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 | Annotate | Revision Log
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 4
5 /** 5 /**
6 * @constructor 6 * @constructor
7 * @extends {WebInspector.VBox} 7 * @extends {WebInspector.VBox}
8 * @implements {WebInspector.TargetManager.Observer} 8 * @implements {WebInspector.TargetManager.Observer}
9 */ 9 */
10 WebInspector.AnimationTimeline = function() 10 WebInspector.AnimationTimeline = function()
(...skipping 11 matching lines...) Expand all
22 this.contentElement.appendChild(this._createHeader()); 22 this.contentElement.appendChild(this._createHeader());
23 this._animationsContainer = this.contentElement.createChild("div", "animatio n-timeline-rows"); 23 this._animationsContainer = this.contentElement.createChild("div", "animatio n-timeline-rows");
24 this._duration = this._defaultDuration(); 24 this._duration = this._defaultDuration();
25 this._scrubberRadius = 25; 25 this._scrubberRadius = 25;
26 this._timelineControlsWidth = 200; 26 this._timelineControlsWidth = 200;
27 /** @type {!Map.<!DOMAgent.BackendNodeId, !WebInspector.AnimationTimeline.No deUI>} */ 27 /** @type {!Map.<!DOMAgent.BackendNodeId, !WebInspector.AnimationTimeline.No deUI>} */
28 this._nodesMap = new Map(); 28 this._nodesMap = new Map();
29 this._symbol = Symbol("animationTimeline"); 29 this._symbol = Symbol("animationTimeline");
30 /** @type {!Map.<string, !WebInspector.AnimationModel.AnimationPlayer>} */ 30 /** @type {!Map.<string, !WebInspector.AnimationModel.AnimationPlayer>} */
31 this._animationsMap = new Map(); 31 this._animationsMap = new Map();
32 this._timelineBezierEditor = new WebInspector.AnimationTimeline.BezierEditor ();
33
32 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNav igated, this); 34 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNav igated, this);
33 WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspec tor.DOMModel.Events.NodeRemoved, this._nodeRemoved, this); 35 WebInspector.targetManager.addModelListener(WebInspector.DOMModel, WebInspec tor.DOMModel.Events.NodeRemoved, this._nodeRemoved, this);
34 36
35 WebInspector.targetManager.observeTargets(this); 37 WebInspector.targetManager.observeTargets(this);
36 } 38 }
37 39
38 WebInspector.AnimationTimeline.GlobalPlaybackRates = [0.1, 0.25, 0.5, 1.0]; 40 WebInspector.AnimationTimeline.GlobalPlaybackRates = [0.1, 0.25, 0.5, 1.0];
39 41
40 WebInspector.AnimationTimeline.prototype = { 42 WebInspector.AnimationTimeline.prototype = {
41 wasShown: function() 43 wasShown: function()
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 _scrubberDragEnd: function(event) 566 _scrubberDragEnd: function(event)
565 { 567 {
566 if (this._scrubberPlayer.currentTime < this.duration() - this._scrubberR adius / this.pixelMsRatio()) 568 if (this._scrubberPlayer.currentTime < this.duration() - this._scrubberR adius / this.pixelMsRatio())
567 this._scrubberPlayer.play(); 569 this._scrubberPlayer.play();
568 this._timelineScrubberHead.window().requestAnimationFrame(this._updateSc rubber.bind(this)); 570 this._timelineScrubberHead.window().requestAnimationFrame(this._updateSc rubber.bind(this));
569 var target = WebInspector.targetManager.mainTarget(); 571 var target = WebInspector.targetManager.mainTarget();
570 if (target) 572 if (target)
571 target.animationModel.setPlaybackRate(this._playbackRate()); 573 target.animationModel.setPlaybackRate(this._playbackRate());
572 }, 574 },
573 575
576 /**
577 * @return {!WebInspector.AnimationTimeline.BezierEditor}
578 */
579 bezierEditor: function()
580 {
581 return this._timelineBezierEditor;
582 },
583
574 __proto__: WebInspector.VBox.prototype 584 __proto__: WebInspector.VBox.prototype
575 } 585 }
576 586
577 /** 587 /**
578 * @constructor 588 * @constructor
579 * @param {!WebInspector.AnimationModel.AnimationNode} animationNode 589 * @param {!WebInspector.AnimationModel.AnimationNode} animationNode
580 */ 590 */
581 WebInspector.AnimationTimeline.NodeUI = function(animationNode) { 591 WebInspector.AnimationTimeline.NodeUI = function(animationNode) {
582 /** 592 /**
583 * @param {?WebInspector.DOMNode} node 593 * @param {?WebInspector.DOMNode} node
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 this._animation = animation; 694 this._animation = animation;
685 this._timeline = timeline; 695 this._timeline = timeline;
686 this._parentElement = parentElement; 696 this._parentElement = parentElement;
687 697
688 if (this._animation.source().keyframesRule()) 698 if (this._animation.source().keyframesRule())
689 this._keyframes = this._animation.source().keyframesRule().keyframes(); 699 this._keyframes = this._animation.source().keyframesRule().keyframes();
690 700
691 this._nameElement = parentElement.createChild("div", "animation-name"); 701 this._nameElement = parentElement.createChild("div", "animation-name");
692 this._nameElement.textContent = this._animation.name(); 702 this._nameElement.textContent = this._animation.name();
693 703
704 this._bezierIconElement = WebInspector.BezierPopoverIcon.createIcon(parentEl ement);
705 this._bezierIconElement.style.backgroundColor = this._color();
706 var editor = this._timeline.bezierEditor();
707 this._bezierIconElement.addEventListener("mousedown", editor.toggle.bind(edi tor, this, this._bezierIconElement));
708
694 this._svg = parentElement.createSVGChild("svg", "animation-ui"); 709 this._svg = parentElement.createSVGChild("svg", "animation-ui");
695 this._svg.setAttribute("height", WebInspector.AnimationUI.Options.AnimationS VGHeight); 710 this._svg.setAttribute("height", WebInspector.AnimationUI.Options.AnimationS VGHeight);
696 this._svg.style.marginLeft = "-" + WebInspector.AnimationUI.Options.Animatio nMargin + "px"; 711 this._svg.style.marginLeft = "-" + WebInspector.AnimationUI.Options.Animatio nMargin + "px";
697 this._svg.addEventListener("mousedown", this._mouseDown.bind(this, WebInspec tor.AnimationUI.MouseEvents.AnimationDrag, null)); 712 this._svg.addEventListener("mousedown", this._mouseDown.bind(this, WebInspec tor.AnimationUI.MouseEvents.AnimationDrag, null));
698 this._activeIntervalGroup = this._svg.createSVGChild("g"); 713 this._activeIntervalGroup = this._svg.createSVGChild("g");
714 this._activeIntervalGroup.addEventListener("mouseover", this._toggleBezierIc on.bind(this, true));
715 this._activeIntervalGroup.addEventListener("mouseout", this._toggleBezierIco n.bind(this, false));
699 716
700 /** @type {!Array.<{group: ?Element, animationLine: ?Element, keyframePoints : !Object.<number, !Element>, keyframeRender: !Object.<number, !Element>}>} */ 717 /** @type {!Array.<{group: ?Element, animationLine: ?Element, keyframePoints : !Object.<number, !Element>, keyframeRender: !Object.<number, !Element>}>} */
701 this._cachedElements = []; 718 this._cachedElements = [];
702 719
703 this._movementInMs = 0; 720 this._movementInMs = 0;
704 this.redraw(); 721 this.redraw();
705 } 722 }
706 723
707 /** 724 /**
708 * @enum {string} 725 * @enum {string}
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 var durationWithDelay = this._delay() + this._duration() * this._animati on.source().iterations() + this._animation.source().endDelay(); 878 var durationWithDelay = this._delay() + this._duration() * this._animati on.source().iterations() + this._animation.source().endDelay();
862 var leftMargin = ((this._animation.startTime() - this._timeline.startTim e()) * this._timeline.pixelMsRatio()); 879 var leftMargin = ((this._animation.startTime() - this._timeline.startTim e()) * this._timeline.pixelMsRatio());
863 var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options .AnimationMargin - leftMargin; 880 var maxWidth = this._timeline.width() - WebInspector.AnimationUI.Options .AnimationMargin - leftMargin;
864 var svgWidth = Math.min(maxWidth, durationWithDelay * this._timeline.pix elMsRatio()); 881 var svgWidth = Math.min(maxWidth, durationWithDelay * this._timeline.pix elMsRatio());
865 882
866 this._svg.classList.toggle("animation-ui-canceled", this._animation.play State() === "idle"); 883 this._svg.classList.toggle("animation-ui-canceled", this._animation.play State() === "idle");
867 this._svg.setAttribute("width", (svgWidth + 2 * WebInspector.AnimationUI .Options.AnimationMargin).toFixed(2)); 884 this._svg.setAttribute("width", (svgWidth + 2 * WebInspector.AnimationUI .Options.AnimationMargin).toFixed(2));
868 this._svg.style.transform = "translateX(" + leftMargin.toFixed(2) + "px )"; 885 this._svg.style.transform = "translateX(" + leftMargin.toFixed(2) + "px )";
869 this._activeIntervalGroup.style.transform = "translateX(" + (this._delay () * this._timeline.pixelMsRatio()).toFixed(2) + "px)"; 886 this._activeIntervalGroup.style.transform = "translateX(" + (this._delay () * this._timeline.pixelMsRatio()).toFixed(2) + "px)";
870 887
871 this._nameElement.style.transform = "translateX(" + (leftMargin + this._ delay() * this._timeline.pixelMsRatio() + WebInspector.AnimationUI.Options.Anima tionMargin).toFixed(2) + "px)"; 888 var leftPosition = (leftMargin + this._delay() * this._timeline.pixelMsR atio() + WebInspector.AnimationUI.Options.AnimationMargin).toFixed(2);
889 this._nameElement.style.transform = "translateX(" + leftPosition + "px)" ;
890 this._bezierIconElement.style.marginLeft = leftPosition + "px";
872 this._nameElement.style.width = (this._duration() * this._timeline.pixel MsRatio().toFixed(2)) + "px"; 891 this._nameElement.style.width = (this._duration() * this._timeline.pixel MsRatio().toFixed(2)) + "px";
873 this._drawDelayLine(this._svg); 892 this._drawDelayLine(this._svg);
874 893
875 if (this._animation.type() === "CSSTransition") { 894 if (this._animation.type() === "CSSTransition") {
876 this._renderTransition(); 895 this._renderTransition();
877 return; 896 return;
878 } 897 }
879 898
880 this._renderIteration(this._activeIntervalGroup, 0); 899 this._renderIteration(this._activeIntervalGroup, 0);
881 if (!this._tailGroup) 900 if (!this._tailGroup)
882 this._tailGroup = this._activeIntervalGroup.createSVGChild("g", "ani mation-tail-iterations"); 901 this._tailGroup = this._activeIntervalGroup.createSVGChild("g", "ani mation-tail-iterations");
883 var iterationWidth = this._duration() * this._timeline.pixelMsRatio(); 902 var iterationWidth = this._duration() * this._timeline.pixelMsRatio();
884 for (var iteration = 1; iteration < this._animation.source().iterations( ) && iterationWidth * (iteration - 1) < this._timeline.width(); iteration++) 903 for (var iteration = 1; iteration < this._animation.source().iterations( ) && iterationWidth * (iteration - 1) < this._timeline.width(); iteration++)
885 this._renderIteration(this._tailGroup, iteration); 904 this._renderIteration(this._tailGroup, iteration);
886 while (iteration < this._cachedElements.length) 905 while (iteration < this._cachedElements.length)
887 this._cachedElements.pop().group.remove(); 906 this._cachedElements.pop().group.remove();
888 }, 907 },
889 908
890
891 _renderTransition: function() 909 _renderTransition: function()
892 { 910 {
893 if (!this._cachedElements[0]) 911 if (!this._cachedElements[0])
894 this._cachedElements[0] = { animationLine: null, keyframePoints: {}, keyframeRender: {}, group: null }; 912 this._cachedElements[0] = { animationLine: null, keyframePoints: {}, keyframeRender: {}, group: null };
895 this._drawAnimationLine(0, this._activeIntervalGroup); 913 this._drawAnimationLine(0, this._activeIntervalGroup);
896 this._renderKeyframe(0, 0, this._activeIntervalGroup, WebInspector.Anima tionUI.Options.AnimationMargin, this._duration() * this._timeline.pixelMsRatio() , this._animation.source().easing()); 914 this._renderKeyframe(0, 0, this._activeIntervalGroup, WebInspector.Anima tionUI.Options.AnimationMargin, this._duration() * this._timeline.pixelMsRatio() , this._animation.source().easing());
897 this._drawPoint(0, this._activeIntervalGroup, WebInspector.AnimationUI.O ptions.AnimationMargin, 0, true); 915 this._drawPoint(0, this._activeIntervalGroup, WebInspector.AnimationUI.O ptions.AnimationMargin, 0, true);
898 this._drawPoint(0, this._activeIntervalGroup, this._duration() * this._t imeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1, t rue); 916 this._drawPoint(0, this._activeIntervalGroup, this._duration() * this._t imeline.pixelMsRatio() + WebInspector.AnimationUI.Options.AnimationMargin, -1, t rue);
899 }, 917 },
900 918
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 this._parentElement.ownerDocument.removeEventListener("mousemove", this. _mouseMoveHandler); 1041 this._parentElement.ownerDocument.removeEventListener("mousemove", this. _mouseMoveHandler);
1024 this._parentElement.ownerDocument.removeEventListener("mouseup", this._m ouseUpHandler); 1042 this._parentElement.ownerDocument.removeEventListener("mouseup", this._m ouseUpHandler);
1025 delete this._mouseMoveHandler; 1043 delete this._mouseMoveHandler;
1026 delete this._mouseUpHandler; 1044 delete this._mouseUpHandler;
1027 delete this._mouseEventType; 1045 delete this._mouseEventType;
1028 delete this._downMouseX; 1046 delete this._downMouseX;
1029 delete this._keyframeMoved; 1047 delete this._keyframeMoved;
1030 }, 1048 },
1031 1049
1032 /** 1050 /**
1051 * @param {boolean} show
1052 */
1053 _toggleBezierIcon: function(show)
1054 {
1055 var bezier = WebInspector.Geometry.CubicBezier.parse(this._animation.sou rce().easing());
1056 if (show && (this._animation.playState() === "idle" || !bezier))
1057 return;
1058 this._bezierIconElement.classList.toggle("shown", show);
1059 },
1060
1061 /**
1062 * @param {string} value
1063 */
1064 _setEasing: function(value)
1065 {
1066 if (!this._node || this._animation.source().easing() == value)
dgozman 2015/05/26 12:02:23 ===
samli 2015/05/27 05:21:59 Done.
1067 return;
1068
1069 this._animation.source().setEasing(value);
1070 this.redraw();
1071
1072 var animationType = this._animation.type();
1073 if (animationType !== "CSSAnimation") {
1074 var target = WebInspector.targetManager.mainTarget();
1075 if (target)
1076 target.animationAgent().setEasing(this._animation.id(), value);
dgozman 2015/05/26 12:02:23 UI should not call animationAgent() and operate wi
samli 2015/05/27 05:21:59 Ack.
1077 }
1078
1079 if (animationType !== "WebAnimation")
1080 this._setNodeStyle(animationType === "CSSTransition" ? "transition-t iming-function" : "animation-timing-function", value);
1081 },
1082
1083 /**
1033 * @param {number} value 1084 * @param {number} value
1034 */ 1085 */
1035 _setDelay: function(value) 1086 _setDelay: function(value)
1036 { 1087 {
1037 if (!this._node || this._animation.source().delay() == this._delay()) 1088 if (!this._node || this._animation.source().delay() == this._delay())
1038 return; 1089 return;
1039 1090
1040 this._animation.source().setDelay(this._delay()); 1091 this._animation.source().setDelay(this._delay());
1041 var propertyName; 1092 var propertyName;
1042 if (this._animation.type() == "CSSTransition") 1093 if (this._animation.type() == "CSSTransition")
(...skipping 27 matching lines...) Expand all
1070 /** 1121 /**
1071 * @param {string} name 1122 * @param {string} name
1072 * @param {string} value 1123 * @param {string} value
1073 */ 1124 */
1074 _setNodeStyle: function(name, value) 1125 _setNodeStyle: function(name, value)
1075 { 1126 {
1076 var style = this._node.getAttribute("style") || ""; 1127 var style = this._node.getAttribute("style") || "";
1077 if (style) 1128 if (style)
1078 style = style.replace(new RegExp("\\s*(-webkit-)?" + name + ":[^;]*; ?\\s*", "g"), ""); 1129 style = style.replace(new RegExp("\\s*(-webkit-)?" + name + ":[^;]*; ?\\s*", "g"), "");
1079 var valueString = name + ": " + value; 1130 var valueString = name + ": " + value;
1080 this._node.setAttributeValue("style", style + " " + valueString + "; -we bkit-" + valueString + ";"); 1131 this._node.setAttributeValue("style", style + " " + valueString + ";");
1081 }, 1132 },
1082 1133
1083 /** 1134 /**
1084 * @return {string} 1135 * @return {string}
1085 */ 1136 */
1086 _color: function() 1137 _color: function()
1087 { 1138 {
1088 /** 1139 /**
1089 * @param {string} string 1140 * @param {string} string
1090 * @return {number} 1141 * @return {number}
(...skipping 28 matching lines...) Expand all
1119 "Light Blue": WebInspector.Color.parse("#03A9F4"), 1170 "Light Blue": WebInspector.Color.parse("#03A9F4"),
1120 "Deep Orange": WebInspector.Color.parse("#FF5722"), 1171 "Deep Orange": WebInspector.Color.parse("#FF5722"),
1121 "Blue": WebInspector.Color.parse("#5677FC"), 1172 "Blue": WebInspector.Color.parse("#5677FC"),
1122 "Lime": WebInspector.Color.parse("#CDDC39"), 1173 "Lime": WebInspector.Color.parse("#CDDC39"),
1123 "Blue Grey": WebInspector.Color.parse("#607D8B"), 1174 "Blue Grey": WebInspector.Color.parse("#607D8B"),
1124 "Pink": WebInspector.Color.parse("#E91E63"), 1175 "Pink": WebInspector.Color.parse("#E91E63"),
1125 "Green": WebInspector.Color.parse("#0F9D58"), 1176 "Green": WebInspector.Color.parse("#0F9D58"),
1126 "Brown": WebInspector.Color.parse("#795548"), 1177 "Brown": WebInspector.Color.parse("#795548"),
1127 "Cyan": WebInspector.Color.parse("#00BCD4") 1178 "Cyan": WebInspector.Color.parse("#00BCD4")
1128 } 1179 }
1180
1181 /**
1182 * @constructor
1183 */
1184 WebInspector.AnimationTimeline.BezierEditor = function()
1185 {
1186 this._popover = new WebInspector.Popover();
1187 this._popover.setCanShrink(false);
1188 this._popover.setNoMargins(true);
1189 this._bezierEditor = new WebInspector.BezierEditor();
1190 this._boundOnKeyDown = this._onKeyDown.bind(this);
1191 this._boundOnFocusOut = this._onFocusOut.bind(this);
1192 }
1193
1194 WebInspector.AnimationTimeline.BezierEditor.prototype = {
dgozman 2015/05/26 12:02:23 That's quite a lot of code duplication. Perhaps, w
samli 2015/05/27 05:21:59 Reluctantly done.
1195 /**
1196 * @param {!WebInspector.AnimationUI} animationUI
1197 * @param {!Element} anchorElement
1198 * @param {!Event} event
1199 */
1200 toggle: function(animationUI, anchorElement, event)
1201 {
1202 var shouldShow = !this._popover.isShowing() || this._animationUI !== ani mationUI;
1203 if (this._popover.isShowing())
1204 this._hide(true);
1205 if (shouldShow)
1206 this._show(animationUI, anchorElement, event);
1207 event.stopPropagation();
1208 event.preventDefault();
1209 },
1210
1211 /**
1212 * @param {!WebInspector.AnimationUI} animationUI
1213 * @param {!Element} anchorElement
1214 * @param {!Event} event
1215 */
1216 _show: function(animationUI, anchorElement, event)
1217 {
1218 this._animationUI = animationUI;
1219 this._anchorElement = anchorElement;
1220 this._previousFocusElement = WebInspector.currentFocusElement();
1221
1222 this._originalEasing = this._animationUI.animation().source().easing();
1223 var bezier = WebInspector.Geometry.CubicBezier.parse(this._originalEasin g);
1224 this._bezierEditor.setBezier(bezier);
1225 this._bezierEditor.addEventListener(WebInspector.BezierEditor.Events.Bez ierChanged, this._bezierChanged, this);
1226 this._popover.showView(this._bezierEditor, this._anchorElement);
1227 this._bezierEditor.contentElement.addEventListener("keydown", this._boun dOnKeyDown);
1228 this._bezierEditor.contentElement.addEventListener("focusout", this._bou ndOnFocusOut);
1229 this._anchorElement.classList.add("bezier-editor-open");
1230 WebInspector.setCurrentFocusElement(this._bezierEditor.contentElement);
1231 },
1232
1233 /**
1234 * @param {boolean=} commitEdit
1235 */
1236 _hide: function(commitEdit)
1237 {
1238 if (!this._popover.isShowing())
1239 return;
1240 this._anchorElement.classList.remove("bezier-editor-open");
1241 this._bezierEditor.removeEventListener(WebInspector.BezierEditor.Events. BezierChanged, this._bezierChanged, this);
1242 if (!commitEdit)
1243 this._animationUI._setEasing(this._originalEasing);
1244 this._popover.hide();
1245 this._bezierEditor.detach();
1246 this._bezierEditor.contentElement.removeEventListener("keydown", this._b oundOnKeyDown);
1247 this._bezierEditor.contentElement.removeEventListener("focusout", this._ boundOnFocusOut);
1248 WebInspector.setCurrentFocusElement(this._previousFocusElement);
1249 },
1250
1251 /**
1252 * @param {!Event} event
1253 */
1254 _onFocusOut: function(event)
1255 {
1256 this._hide(true);
1257 },
1258
1259 /**
1260 * @param {!Event} event
1261 */
1262 _onKeyDown: function(event)
1263 {
1264 if (event.keyIdentifier === "Enter") {
1265 this._hide(true);
1266 event.consume(true);
1267 return;
1268 }
1269 if (event.keyIdentifier === "U+001B") { // Escape key
1270 this._hide(false);
1271 event.consume(true);
1272 }
1273 },
1274
1275 /**
1276 * @param {!WebInspector.Event} event
1277 */
1278 _bezierChanged: function(event)
1279 {
1280 this._animationUI._setEasing(/** @type {string} */ (event.data));
1281 }
1282 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698