Skip to content

Commit 31a2fc6

Browse files
author
Dennis Hergaarden
committed
Use javascript functions to parse CSSStyle values and remove regex
1 parent 6df2b9c commit 31a2fc6

File tree

1 file changed

+73
-123
lines changed

1 file changed

+73
-123
lines changed

src/tweenjs/plugins/CSSPlugin.js

Lines changed: 73 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
* @module TweenJS
3131
*/
3232

33-
this.createjs = this.createjs||{};
33+
this.createjs = this.createjs || {};
3434

35-
(function() {
35+
(function () {
3636
"use strict";
3737

3838
/**
@@ -74,18 +74,18 @@ this.createjs = this.createjs||{};
7474
* @constructor
7575
**/
7676
function CSSPlugin() {
77-
throw("CSSPlugin cannot be instantiated.")
77+
throw ("CSSPlugin cannot be instantiated.")
7878
}
7979
var s = CSSPlugin;
8080

81-
// static properties
81+
// static properties
8282
/**
8383
* @property priority
8484
* @protected
8585
* @static
8686
**/
8787
s.priority = 100; // high priority, should read first and write last
88-
88+
8989
/**
9090
* READ-ONLY. A unique identifying string for this plugin. Used by TweenJS to ensure duplicate plugins are not installed on a tween.
9191
* @property ID
@@ -94,22 +94,8 @@ this.createjs = this.createjs||{};
9494
* @readonly
9595
**/
9696
s.ID = "CSS";
97-
98-
/**
99-
* READ-ONLY.
100-
* @property VALUE_RE
101-
* @type {RegExp}
102-
* @static
103-
* @readonly
104-
*/
105-
s.VALUE_RE = /^(-?[\d.]+)([a-z%]*)$/; // extracts the numeric value and suffix from a single CSS value
106-
107-
s.TRANSFORM_VALUE_RE = /(?:^| |,)(-?[\d.]+)([a-z%]*)/g; // extracts the numeric value and suffix from comma delimited lists
108-
109-
s.TRANSFORM_RE = /(\w+?)\(([^)]+)\)|(?:^| )(\*)(?:$| )/g; // extracts the components of a transform
110-
111-
112-
97+
98+
11399
/**
114100
* By default, CSSPlugin uses only inline styles on the target element (ie. set via the style attribute, `style` property, or `cssText`)
115101
* to determine which properties should be tweened via CSS, and what units to use.
@@ -139,13 +125,13 @@ this.createjs = this.createjs||{};
139125
s.compute = false;
140126

141127

142-
// static methods
128+
// static methods
143129
/**
144130
* Installs this plugin for use with TweenJS. Call this once after TweenJS is loaded to enable this plugin.
145131
* @method install
146132
* @static
147133
**/
148-
s.install = function() {
134+
s.install = function () {
149135
createjs.Tween._installPlugin(CSSPlugin);
150136
};
151137

@@ -159,31 +145,36 @@ this.createjs = this.createjs||{};
159145
* @return {any}
160146
* @static
161147
**/
162-
s.init = function(tween, prop, value) {
148+
s.init = function (tween, prop, value) {
163149
var data = tween.pluginData;
164150
if (data.CSS_disabled || !(tween.target instanceof HTMLElement)) { return; }
165-
var initVal = value||getStyle(tween.target, prop, data.CSS_compute);
166-
if (initVal === undefined) { return; }
167-
151+
var initVal = value || getStyle(tween.target, prop, data.CSS_compute);
152+
153+
154+
if (initVal === undefined) { return; }
155+
168156
tween._addPlugin(CSSPlugin);
169157
var cssData = data.CSS || (data.CSS = {});
170158
if (prop === "transform") {
171159
cssData[prop] = "_t";
172160
return parseTransform(initVal);
173161
}
174-
175-
var result = s.VALUE_RE.exec(initVal);
162+
163+
let result = null;
164+
if (initVal)
165+
result = CSSNumericValue.parse(initVal);
166+
176167
if (result === null) {
177168
// a string we can't handle numerically, so add it to the CSSData without a suffix.
178169
cssData[prop] = "";
179170
return initVal;
180171
} else {
181-
cssData[prop] = result[2];
182-
return parseFloat(result[1]);
172+
cssData[prop] = result.unit;
173+
return result.value;
183174
}
184175
};
185176

186-
177+
187178
/**
188179
* Called when a new step is added to a tween (ie. a new "to" action is added to a tween).
189180
* See {{#crossLink "SamplePlugin/step"}}{{/crossLink}} for more info.
@@ -193,7 +184,7 @@ this.createjs = this.createjs||{};
193184
* @param {Object} props
194185
* @static
195186
**/
196-
s.step = function(tween, step, props) {
187+
s.step = function (tween, step, props) {
197188
if (props.transform) {
198189
step.props.transform = parseTransform(step.props.transform, step.prev.props.transform);
199190
}
@@ -212,7 +203,7 @@ this.createjs = this.createjs||{};
212203
* @return {any}
213204
* @static
214205
**/
215-
s.change = function(tween, step, prop, value, ratio, end) {
206+
s.change = function (tween, step, prop, value, ratio, end) {
216207
var sfx = tween.pluginData.CSS[prop];
217208
if (sfx === undefined) { return; }
218209
if (prop === "transform") {
@@ -223,9 +214,9 @@ this.createjs = this.createjs||{};
223214
tween.target.style[prop] = value;
224215
return createjs.Tween.IGNORE;
225216
};
226-
227-
228-
// private helper methods:
217+
218+
219+
// private helper methods:
229220
function getStyle(target, prop, compute) {
230221
if (compute || (compute == null && s.compute)) {
231222
return window.getComputedStyle(target)[prop];
@@ -234,104 +225,63 @@ this.createjs = this.createjs||{};
234225
}
235226
}
236227

237-
function parseTransform(str, compare) {
238-
var result, list = [false, str];
239-
do {
240-
// pull out the next "component" of the transform (ex. "translate(10px, 20px)")
241-
result = s.TRANSFORM_RE.exec(str);
242-
if (!result) { break; }
243-
if (result[3] === "*") {
244-
// reuse previous value:
245-
list.push(compare[list.length]);
246-
continue;
247-
}
248-
var component = [result[1]], compareComp = compare && compare[list.length];
249-
250-
// check that the operation type matches (ex. "translate" vs "rotate"):
251-
if (compare && (!compareComp || component[0] !== compareComp[0])) {
252-
console.log("transforms don't match: ", component[0], compareComp&&compareComp[0]);
253-
compare=null;
254-
} // component doesn't match
255-
256-
parseMulti(result[2], compareComp, component);
228+
const parseTransform = (str, compare) => {
229+
let list = [false];
230+
let result = CSSStyleValue.parse("transform", str);
231+
list.push(result);
257232

258-
list.push(component);
259-
} while(true);
233+
if (compare && compare.length === result.length) {
234+
for (let i = 0; i < result.length; i++) {
235+
if (compare[1][i].constructor !== result[i].constructor) {
236+
console.log("transforms don't match: ", result[0].constructor.name, compare[1][i].constructor.name);
237+
compare = null;
238+
} // component doesn't match
239+
}
240+
}
260241

242+
// Return false when compare is undefined/null
261243
list[0] = !!compare;
262-
return list;
263-
}
264-
265-
// this was separated so that it can be used for other multi element styles in the future
266-
// ex. transform-origin, border, etc.
267-
function parseMulti(str, compare, arr) {
268-
// TODO: add logic to deal with "0" values? Troublesome because the browser automatically appends a unit for some 0 values.
269-
do {
270-
// pull out the next value (ex. "20px", "12.4rad"):
271-
var result = s.TRANSFORM_VALUE_RE.exec(str);
272-
if (!result) { return arr; }
273-
if (!arr) { arr = []; }
274-
arr.push(+result[1], result[2]);
275-
276-
// check that the units match (ex. "px" vs "em"):
277-
if (compare && (compare[arr.length-1] !== result[2])) { console.log("transform units don't match: ",arr[0], compare[arr.length-1], result[2]); compare=null; } // unit doesn't match
278-
} while(true);
244+
return (list);
279245
}
280246

281247
function writeTransform(list0, list1, ratio) {
282248
// check if we should just use the original transform strings:
283-
if (ratio === 1) { return list1[1]; }
284-
if (ratio === 0 || !list1[0]) { return list0[1]; }
249+
if (ratio === 1) { return list1[1].toString(); }
250+
if (ratio === 0 || !list1[0]) { return list0[1].toString(); }
285251

286252
// they match, we want to apply the ratio:
287-
var str = "", l=list0.length, i, j, jl;
288-
for (i=2; i<l; i++) {
289-
var component0 = list0[i], component1 = list1[i];
290-
str += component0[0]+"(";
291-
for (j=1, jl=component0.length; j<jl; j+=2) {
292-
str += component0[j]+(component1[j]-component0[j])*ratio; // value
293-
str += component1[j+1] || component0[j+1]; // unit
294-
if (j < jl-2) { str += ", "; }
295-
}
296-
str += ")";
297-
if (i < l-1) { str += " "; }
298-
}
299-
return str;
300-
}
301-
302-
/*
303-
304-
// this was part of an attempt to handle multi element css values, ex. margin="10px 10px 20px 30px"
305-
// discarded because the browser likes to collapse values, which makes a generic solution infeasible.
306-
// for example, margin="10px 10px 10px 10px" will collapse to just "10px"
307-
// requires custom logic to handle each scenario.
308-
s.MULTI_RE = /((?:^| )-?[\d.]+[a-z%]*){2,}/; // matches CSS values that consist of two or more values with suffixes
309-
function writeMulti(arr0, arr1, ratio) {
310-
var str = "", l=arr0.length, i;
311-
for (i=0; i<l; i+=2) {
312-
str += arr0[i]+(arr1[i]-arr0[i])*ratio+arr0[i+1];
313-
if (i < l-2) { str += " "; }
314-
}
315-
return str;
316-
}
317-
318-
// this method is really only needed for roundtrip tests.
319-
function writeSingleTransform(list) {
320-
var str = "", l=list.length, i, j, jl, component;
321-
for (i=2; i<l; i++) {
322-
component = list[i];
323-
str += component[0]+"(";
324-
for (j=1, jl=component.length; j<jl; j+=2) {
325-
str += component[j]+component[j+1];
326-
if (j < jl-2) { str += ", "; }
253+
let original = list0[1];
254+
let modifiedValue = CSSStyleValue.parse("transform", original.toString());
255+
let newValue = list1[1];
256+
257+
// Only works for rotate, scale and translate, skew or metrix do not have x,y,z
258+
for (let i = 0; i < original.length; i++) {
259+
switch (original[i].constructor) {
260+
case CSSRotate:
261+
modifiedValue[i].angle.value += (newValue[i].angle.value - original[i].angle.value) * ratio;
262+
// Fall down to CSSScale to set x,y,z
263+
case CSSTranslate:
264+
// Fall down to CSSScale to set x,y,z
265+
case CSSScale:
266+
modifiedValue[i].x.value += (newValue[i].x.value - original[i].x.value) * ratio;
267+
modifiedValue[i].y.value += (newValue[i].y.value - original[i].y.value) * ratio;
268+
modifiedValue[i].z.value += (newValue[i].z.value - original[i].z.value) * ratio;
269+
break;
270+
case CSSSkew:
271+
modifiedValue[i].ax.value += (newValue[i].ax.value - original[i].ax.value) * ratio;
272+
modifiedValue[i].ay.value += (newValue[i].ay.value - original[i].ay.value) * ratio;
273+
break;
274+
case CSSSkewX:
275+
modifiedValue[i].ax.value += (newValue[i].ax.value - original[i].ax.value) * ratio;
276+
break;
277+
case CSSSkewY:
278+
modifiedValue[i].ay.value += (newValue[i].ay.value - original[i].ay.value) * ratio;
279+
break;
327280
}
328-
str += ")";
329-
if (i < l-1) { str += " "; }
330281
}
331-
return str;
282+
return modifiedValue.toString();
332283
}
333-
*/
334-
284+
335285
createjs.CSSPlugin = s;
336286

337287
}());

0 commit comments

Comments
 (0)