| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * @constructor | |
| 7 * @extends {WebInspector.VBox} | |
| 8 */ | |
| 9 WebInspector.BezierEditor = function() | |
| 10 { | |
| 11 WebInspector.VBox.call(this, true); | |
| 12 this.registerRequiredCSS("elements/bezierEditor.css"); | |
| 13 this.contentElement.tabIndex = 0; | |
| 14 | |
| 15 // Preview UI | |
| 16 this._previewElement = this.contentElement.createChild("div", "bezier-previe
w-container"); | |
| 17 this._previewElement.createChild("div", "bezier-preview-animation"); | |
| 18 this._previewElement.addEventListener("click", this._startPreviewAnimation.b
ind(this)); | |
| 19 this._previewOnion = this.contentElement.createChild("div", "bezier-preview-
onion"); | |
| 20 this._previewOnion.addEventListener("click", this._startPreviewAnimation.bin
d(this)); | |
| 21 | |
| 22 this._outerContainer = this.contentElement.createChild("div", "bezier-contai
ner"); | |
| 23 | |
| 24 // Presets UI | |
| 25 this._presetsContainer = this._outerContainer.createChild("div", "bezier-pre
sets"); | |
| 26 this._presetUI = new WebInspector.BezierUI(40, 40, 0, 2, false); | |
| 27 this._presetCategories = []; | |
| 28 for (var i = 0; i < WebInspector.BezierEditor.Presets.length; i++) { | |
| 29 this._presetCategories[i] = this._createCategory(WebInspector.BezierEdit
or.Presets[i]); | |
| 30 this._presetsContainer.appendChild(this._presetCategories[i].icon); | |
| 31 } | |
| 32 | |
| 33 // Curve UI | |
| 34 this._curveUI = new WebInspector.BezierUI(150, 250, 50, 7, true); | |
| 35 this._curve = this._outerContainer.createSVGChild("svg", "bezier-curve"); | |
| 36 WebInspector.installDragHandle(this._curve, this._dragStart.bind(this), this
._dragMove.bind(this), this._dragEnd.bind(this), "default"); | |
| 37 | |
| 38 this._header = this.contentElement.createChild("div", "bezier-header"); | |
| 39 var minus = this._createPresetModifyIcon(this._header, "bezier-preset-minus"
, "M 12 6 L 8 10 L 12 14"); | |
| 40 var plus = this._createPresetModifyIcon(this._header, "bezier-preset-plus",
"M 8 6 L 12 10 L 8 14"); | |
| 41 minus.addEventListener("click", this._presetModifyClicked.bind(this, false))
; | |
| 42 plus.addEventListener("click", this._presetModifyClicked.bind(this, true)); | |
| 43 this._label = this._header.createChild("span", "source-code bezier-display-v
alue"); | |
| 44 } | |
| 45 | |
| 46 /** @enum {symbol} */ | |
| 47 WebInspector.BezierEditor.Events = { | |
| 48 BezierChanged: Symbol("BezierChanged") | |
| 49 } | |
| 50 | |
| 51 WebInspector.BezierEditor.Presets = [ | |
| 52 [ | |
| 53 { name: "ease-in-out", value: "ease-in-out" }, | |
| 54 { name: "In Out · Sine", value: "cubic-bezier(0.45, 0.05, 0.55, 0.95)" }
, | |
| 55 { name: "In Out · Quadratic", value: "cubic-bezier(0.46, 0.03, 0.52, 0.9
6)" }, | |
| 56 { name: "In Out · Cubic", value: "cubic-bezier(0.65, 0.05, 0.36, 1)" }, | |
| 57 { name: "Fast Out, Slow In", value: "cubic-bezier(0.4, 0, 0.2, 1)" }, | |
| 58 { name: "In Out · Back", value: "cubic-bezier(0.68, -0.55, 0.27, 1.55)"
} | |
| 59 ], | |
| 60 [ | |
| 61 { name: "Fast Out, Linear In", value: "cubic-bezier(0.4, 0, 1, 1)" }, | |
| 62 { name: "ease-in", value: "ease-in" }, | |
| 63 { name: "In · Sine", value: "cubic-bezier(0.47, 0, 0.75, 0.72)" }, | |
| 64 { name: "In · Quadratic", value: "cubic-bezier(0.55, 0.09, 0.68, 0.53)"
}, | |
| 65 { name: "In · Cubic", value: "cubic-bezier(0.55, 0.06, 0.68, 0.19)" }, | |
| 66 { name: "In · Back", value: "cubic-bezier(0.6, -0.28, 0.74, 0.05)" } | |
| 67 ], | |
| 68 [ | |
| 69 { name: "ease-out", value: "ease-out" }, | |
| 70 { name: "Out · Sine", value: "cubic-bezier(0.39, 0.58, 0.57, 1)" }, | |
| 71 { name: "Out · Quadratic", value: "cubic-bezier(0.25, 0.46, 0.45, 0.94)"
}, | |
| 72 { name: "Out · Cubic", value: "cubic-bezier(0.22, 0.61, 0.36, 1)" }, | |
| 73 { name: "Linear Out, Slow In", value: "cubic-bezier(0, 0, 0.2, 1)" }, | |
| 74 { name: "Out · Back", value: "cubic-bezier(0.18, 0.89, 0.32, 1.28)" } | |
| 75 ] | |
| 76 ] | |
| 77 | |
| 78 /** @typedef {{presets: !Array.<{name: string, value: string}>, icon: !Element,
presetIndex: number}} */ | |
| 79 WebInspector.BezierEditor.PresetCategory; | |
| 80 | |
| 81 WebInspector.BezierEditor.prototype = { | |
| 82 /** | |
| 83 * @param {?WebInspector.Geometry.CubicBezier} bezier | |
| 84 */ | |
| 85 setBezier: function(bezier) | |
| 86 { | |
| 87 if (!bezier) | |
| 88 return; | |
| 89 this._bezier = bezier; | |
| 90 this._updateUI(); | |
| 91 }, | |
| 92 | |
| 93 /** | |
| 94 * @return {!WebInspector.Geometry.CubicBezier} | |
| 95 */ | |
| 96 bezier: function() | |
| 97 { | |
| 98 return this._bezier; | |
| 99 }, | |
| 100 | |
| 101 wasShown: function() | |
| 102 { | |
| 103 this._unselectPresets(); | |
| 104 // Check if bezier matches a preset | |
| 105 for (var category of this._presetCategories) { | |
| 106 for (var i = 0; i < category.presets.length; i++) { | |
| 107 if (this._bezier.asCSSText() === category.presets[i].value) { | |
| 108 category.presetIndex = i; | |
| 109 this._presetCategorySelected(category); | |
| 110 } | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 this._updateUI(); | |
| 115 this._startPreviewAnimation(); | |
| 116 }, | |
| 117 | |
| 118 _onchange: function() | |
| 119 { | |
| 120 this._updateUI(); | |
| 121 this.dispatchEventToListeners(WebInspector.BezierEditor.Events.BezierCha
nged, this._bezier.asCSSText()); | |
| 122 }, | |
| 123 | |
| 124 _updateUI: function() | |
| 125 { | |
| 126 var labelText = this._selectedCategory ? this._selectedCategory.presets[
this._selectedCategory.presetIndex].name : this._bezier.asCSSText().replace(/\s(
-\d\.\d)/g, "$1"); | |
| 127 this._label.textContent = WebInspector.UIString(labelText); | |
| 128 this._curveUI.drawCurve(this._bezier, this._curve); | |
| 129 this._previewOnion.removeChildren(); | |
| 130 }, | |
| 131 | |
| 132 /** | |
| 133 * @param {!Event} event | |
| 134 * @return {boolean} | |
| 135 */ | |
| 136 _dragStart: function(event) | |
| 137 { | |
| 138 this._mouseDownPosition = new WebInspector.Geometry.Point(event.x, event
.y); | |
| 139 var ui = this._curveUI; | |
| 140 this._controlPosition = new WebInspector.Geometry.Point( | |
| 141 Number.constrain((event.offsetX - ui.radius) / ui.curveWidth(), 0, 1
), | |
| 142 (ui.curveHeight() + ui.marginTop + ui.radius - event.offsetY) / ui.c
urveHeight()); | |
| 143 | |
| 144 var firstControlPointIsCloser = this._controlPosition.distanceTo(this._b
ezier.controlPoints[0]) < this._controlPosition.distanceTo(this._bezier.controlP
oints[1]); | |
| 145 this._selectedPoint = firstControlPointIsCloser ? 0 : 1; | |
| 146 | |
| 147 this._bezier.controlPoints[this._selectedPoint] = this._controlPosition; | |
| 148 this._unselectPresets(); | |
| 149 this._onchange(); | |
| 150 | |
| 151 event.consume(true); | |
| 152 return true; | |
| 153 }, | |
| 154 | |
| 155 /** | |
| 156 * @param {number} mouseX | |
| 157 * @param {number} mouseY | |
| 158 */ | |
| 159 _updateControlPosition: function(mouseX, mouseY) | |
| 160 { | |
| 161 var deltaX = (mouseX - this._mouseDownPosition.x) / this._curveUI.curveW
idth(); | |
| 162 var deltaY = (mouseY - this._mouseDownPosition.y) / this._curveUI.curveH
eight(); | |
| 163 var newPosition = new WebInspector.Geometry.Point(Number.constrain(this.
_controlPosition.x + deltaX, 0, 1), this._controlPosition.y - deltaY); | |
| 164 this._bezier.controlPoints[this._selectedPoint] = newPosition; | |
| 165 }, | |
| 166 | |
| 167 /** | |
| 168 * @param {!Event} event | |
| 169 */ | |
| 170 _dragMove: function(event) | |
| 171 { | |
| 172 this._updateControlPosition(event.x, event.y); | |
| 173 this._onchange(); | |
| 174 }, | |
| 175 | |
| 176 /** | |
| 177 * @param {!Event} event | |
| 178 */ | |
| 179 _dragEnd: function(event) | |
| 180 { | |
| 181 this._updateControlPosition(event.x, event.y); | |
| 182 this._onchange(); | |
| 183 this._startPreviewAnimation(); | |
| 184 }, | |
| 185 | |
| 186 /** | |
| 187 * @param {!Array<{name: string, value: string}>} presetGroup | |
| 188 * @return {!WebInspector.BezierEditor.PresetCategory} | |
| 189 */ | |
| 190 _createCategory: function(presetGroup) | |
| 191 { | |
| 192 var presetElement = createElementWithClass("div", "bezier-preset-categor
y"); | |
| 193 var iconElement = presetElement.createSVGChild("svg", "bezier-preset mon
ospace"); | |
| 194 var category = { presets: presetGroup, presetIndex: 0, icon: presetEleme
nt }; | |
| 195 this._presetUI.drawCurve(WebInspector.Geometry.CubicBezier.parse(categor
y.presets[0].value), iconElement); | |
| 196 iconElement.addEventListener("click", this._presetCategorySelected.bind(
this, category)); | |
| 197 return category; | |
| 198 }, | |
| 199 | |
| 200 /** | |
| 201 * @param {!Element} parentElement | |
| 202 * @param {string} className | |
| 203 * @param {string} drawPath | |
| 204 * @return {!Element} | |
| 205 */ | |
| 206 _createPresetModifyIcon: function(parentElement, className, drawPath) | |
| 207 { | |
| 208 var icon = parentElement.createSVGChild("svg", "bezier-preset-modify " +
className); | |
| 209 icon.setAttribute("width", 20); | |
| 210 icon.setAttribute("height", 20); | |
| 211 var path = icon.createSVGChild("path"); | |
| 212 path.setAttribute("d", drawPath); | |
| 213 return icon; | |
| 214 }, | |
| 215 | |
| 216 _unselectPresets: function() | |
| 217 { | |
| 218 for (var category of this._presetCategories) | |
| 219 category.icon.classList.remove("bezier-preset-selected"); | |
| 220 delete this._selectedCategory; | |
| 221 this._header.classList.remove("bezier-header-active"); | |
| 222 }, | |
| 223 | |
| 224 /** | |
| 225 * @param {!WebInspector.BezierEditor.PresetCategory} category | |
| 226 * @param {!Event=} event | |
| 227 */ | |
| 228 _presetCategorySelected: function(category, event) | |
| 229 { | |
| 230 if (this._selectedCategory === category) | |
| 231 return; | |
| 232 this._unselectPresets(); | |
| 233 this._header.classList.add("bezier-header-active"); | |
| 234 this._selectedCategory = category; | |
| 235 this._selectedCategory.icon.classList.add("bezier-preset-selected"); | |
| 236 this.setBezier(WebInspector.Geometry.CubicBezier.parse(category.presets[
category.presetIndex].value)); | |
| 237 this._onchange(); | |
| 238 this._startPreviewAnimation(); | |
| 239 if (event) | |
| 240 event.consume(true); | |
| 241 }, | |
| 242 | |
| 243 /** | |
| 244 * @param {boolean} intensify | |
| 245 * @param {!Event} event | |
| 246 */ | |
| 247 _presetModifyClicked: function(intensify, event) | |
| 248 { | |
| 249 if (!this._selectedCategory) | |
| 250 return; | |
| 251 | |
| 252 var length = this._selectedCategory.presets.length; | |
| 253 this._selectedCategory.presetIndex = (this._selectedCategory.presetIndex
+ (intensify ? 1 : -1) + length) % length; | |
| 254 this.setBezier(WebInspector.Geometry.CubicBezier.parse(this._selectedCat
egory.presets[this._selectedCategory.presetIndex].value)); | |
| 255 this._onchange(); | |
| 256 this._startPreviewAnimation(); | |
| 257 }, | |
| 258 | |
| 259 _startPreviewAnimation: function() | |
| 260 { | |
| 261 if (this._previewAnimation) | |
| 262 this._previewAnimation.cancel(); | |
| 263 | |
| 264 const animationDuration = 1600; | |
| 265 const numberOnionSlices = 20; | |
| 266 | |
| 267 var keyframes = [{ offset: 0, transform: "translateX(0px)", easing: this
._bezier.asCSSText(), opacity: 1 }, | |
| 268 { offset: 0.9, transform: "translateX(218px)", opacity: 1 }, | |
| 269 { offset: 1, transform: "translateX(218px)", opacity: 0 }]; | |
| 270 this._previewAnimation = this._previewElement.animate(keyframes, animati
onDuration); | |
| 271 this._previewOnion.removeChildren(); | |
| 272 for (var i = 0; i <= numberOnionSlices; i++) { | |
| 273 var slice = this._previewOnion.createChild("div", "bezier-preview-an
imation"); | |
| 274 var player = slice.animate([{ transform: "translateX(0px)", easing:
this._bezier.asCSSText() }, { transform: "translateX(218px)" }], | |
| 275 { duration: animationDuration, fill: "forwards" }); | |
| 276 player.pause(); | |
| 277 player.currentTime = animationDuration * i / numberOnionSlices; | |
| 278 } | |
| 279 }, | |
| 280 | |
| 281 __proto__: WebInspector.VBox.prototype | |
| 282 } | |
| OLD | NEW |