Skip to content

Commit ca55be2

Browse files
committed
support percentage in transform() and scale() #111
1 parent b1e1805 commit ca55be2

File tree

13 files changed

+630
-142
lines changed

13 files changed

+630
-142
lines changed

dist/index-umd-web.js

Lines changed: 126 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,9 +4109,6 @@
41094109
function identity() {
41104110
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
41114111
}
4112-
function pLength(point) {
4113-
return Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
4114-
}
41154112
function normalize(point) {
41164113
const [x, y, z] = point;
41174114
const norm = Math.sqrt(point[0] * point[0] + point[1] * point[1] + point[2] * point[2]);
@@ -4232,16 +4229,21 @@
42324229
const row0 = [matrix[0], matrix[1], matrix[2]];
42334230
const row1 = [matrix[4], matrix[5], matrix[6]];
42344231
const row2 = [matrix[8], matrix[9], matrix[10]];
4232+
const cross = [
4233+
row1[1] * row2[2] - row1[2] * row2[1],
4234+
row1[2] * row2[0] - row1[0] * row2[2],
4235+
row1[0] * row2[1] - row1[1] * row2[0],
4236+
];
42354237
// Compute scale
4236-
const scaleX = pLength(row0);
4238+
const scaleX = Math.hypot(...row0);
42374239
const row0Norm = normalize(row0);
42384240
const skewXY = dot(row0Norm, row1);
42394241
const row1Proj = [
42404242
row1[0] - skewXY * row0Norm[0],
42414243
row1[1] - skewXY * row0Norm[1],
42424244
row1[2] - skewXY * row0Norm[2]
42434245
];
4244-
const scaleY = pLength(row1Proj);
4246+
const scaleY = Math.hypot(...row1Proj);
42454247
const row1Norm = normalize(row1Proj);
42464248
const skewXZ = dot(row0Norm, row2);
42474249
const skewYZ = dot(row1Norm, row2);
@@ -4250,8 +4252,9 @@
42504252
row2[1] - skewXZ * row0Norm[1] - skewYZ * row1Norm[1],
42514253
row2[2] - skewXZ * row0Norm[2] - skewYZ * row1Norm[2]
42524254
];
4253-
const scaleZ = pLength(row2Proj);
42544255
const row2Norm = normalize(row2Proj);
4256+
const determinant = row0[0] * cross[0] + row0[1] * cross[1] + row0[2] * cross[2];
4257+
const scaleZ = Math.hypot(...row2Proj) * (determinant < 0 ? -1 : 1);
42554258
// Build rotation matrix from orthonormalized vectors
42564259
const r00 = row0Norm[0], r01 = row1Norm[0], r02 = row2Norm[0];
42574260
const r10 = row0Norm[1], r11 = row1Norm[1], r12 = row2Norm[1];
@@ -4288,7 +4291,6 @@
42884291
qz = 0.25 * s;
42894292
}
42904293
[qx, qy, qz] = toZero([qx, qy, qz]);
4291-
// const q = gcd(qx, gcd(qy, qz));
42924294
let q = [Math.abs(qx), Math.abs(qy), Math.abs(qz)].reduce((acc, curr) => {
42934295
if (acc == 0 || (curr > 0 && curr < acc)) {
42944296
acc = curr;
@@ -21354,7 +21356,7 @@
2135421356
scales.delete('x');
2135521357
}
2135621358
if (scales.size == 1) {
21357-
let prefix = scales.has('x') ? '' : scales.has('y') ? 'Y' : 'Z';
21359+
let prefix = scales.has('x') ? 'X' : scales.has('y') ? 'Y' : 'Z';
2135821360
result.push({
2135921361
typ: exports.EnumToken.FunctionTokenType,
2136021362
val: 'scale' + prefix,
@@ -21419,6 +21421,109 @@
2141921421
}
2142021422
return true;
2142121423
}
21424+
function minifyTransformFunctions(transform) {
21425+
const name = transform.val.toLowerCase();
21426+
if ('skewx' == name) {
21427+
transform.val = 'skew';
21428+
return transform;
21429+
}
21430+
if (!['translate', 'translate3d', 'scale', 'scale3d'].includes(name)) {
21431+
return transform;
21432+
}
21433+
const values = [];
21434+
for (const token of transform.chi) {
21435+
if (token.typ == exports.EnumToken.CommentTokenType || token.typ == exports.EnumToken.WhitespaceTokenType || token.typ == exports.EnumToken.CommaTokenType) {
21436+
continue;
21437+
}
21438+
if (![exports.EnumToken.NumberTokenType, exports.EnumToken.LengthTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType].includes(token.typ)) {
21439+
return transform;
21440+
}
21441+
if (token.typ == exports.EnumToken.PercentageTokenType && typeof token.val == 'number' && name.startsWith('scale')) {
21442+
Object.assign(token, { typ: exports.EnumToken.NumberTokenType, val: token.val / 100 });
21443+
}
21444+
values.push(token);
21445+
}
21446+
if ((name == 'translate' || name == 'scale') && values.length > 2) {
21447+
return transform;
21448+
}
21449+
const ignoredValue = name.startsWith('scale') ? 1 : 0;
21450+
const t = new Set(['x', 'y', 'z']);
21451+
let i = 3;
21452+
while (i--) {
21453+
if (values.length <= i || values[i].val == ignoredValue) {
21454+
t.delete(i == 0 ? 'x' : i == 1 ? 'y' : 'z');
21455+
}
21456+
}
21457+
if (name == 'translate3d' || name == 'translate') {
21458+
if (t.size == 0) {
21459+
return {
21460+
typ: exports.EnumToken.FunctionTokenType,
21461+
val: 'translate',
21462+
chi: [
21463+
{ typ: exports.EnumToken.NumberTokenType, val: 0 }
21464+
]
21465+
};
21466+
}
21467+
if (t.size == 1) {
21468+
return {
21469+
typ: exports.EnumToken.FunctionTokenType,
21470+
val: 'translate' + (t.has('x') ? '' : t.has('y') ? 'Y' : 'Z'),
21471+
chi: [
21472+
values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21473+
]
21474+
};
21475+
}
21476+
if (t.size == 2) {
21477+
if (t.has('z')) {
21478+
return transform;
21479+
}
21480+
return {
21481+
typ: exports.EnumToken.FunctionTokenType,
21482+
val: 'translate',
21483+
chi: [
21484+
values[0],
21485+
{ typ: exports.EnumToken.CommaTokenType },
21486+
values[1]
21487+
]
21488+
};
21489+
}
21490+
}
21491+
if (name == 'scale3d' || name == 'scale') {
21492+
if (t.size == 0) {
21493+
return {
21494+
typ: exports.EnumToken.FunctionTokenType,
21495+
val: 'scale',
21496+
chi: [
21497+
{ typ: exports.EnumToken.NumberTokenType, val: 1 }
21498+
]
21499+
};
21500+
}
21501+
if (t.size == 1) {
21502+
return {
21503+
typ: exports.EnumToken.FunctionTokenType,
21504+
val: 'scale' + (t.has('x') ? 'X' : t.has('y') ? 'Y' : 'Z'),
21505+
chi: [
21506+
values[t.has('x') ? 0 : t.has('y') ? 1 : 2]
21507+
]
21508+
};
21509+
}
21510+
if (t.size == 2) {
21511+
if (t.has('z')) {
21512+
return transform;
21513+
}
21514+
return {
21515+
typ: exports.EnumToken.FunctionTokenType,
21516+
val: 'scale',
21517+
chi: [
21518+
values[0],
21519+
{ typ: exports.EnumToken.CommaTokenType },
21520+
values[1]
21521+
]
21522+
};
21523+
}
21524+
}
21525+
return transform;
21526+
}
2142221527

2142321528
function skewX(x, from) {
2142421529
const matrix = identity();
@@ -21474,8 +21579,6 @@
2147421579
});
2147521580
}
2147621581
}
21477-
// console.error({matrix});
21478-
// matrix = toZero(matrix) as Matrix;
2147921582
return {
2148021583
matrix: serialize(toZero(matrix)),
2148121584
cumulative,
@@ -21499,7 +21602,7 @@
2149921602
{
2150021603
values.length = 0;
2150121604
const children = stripCommaToken(transformList[i].chi.slice());
21502-
const valCount = transformList[i].val == 'translate3d' || transformList[i].val == 'translate' ? 3 : 1;
21605+
const valCount = transformList[i].val == 'translate3d' ? 3 : transformList[i].val == 'translate' ? 2 : 1;
2150321606
for (let j = 0; j < children.length; j++) {
2150421607
if (children[j].typ == exports.EnumToken.WhitespaceTokenType) {
2150521608
continue;
@@ -21586,7 +21689,7 @@
2158621689
const children = stripCommaToken(transformList[i].chi.slice());
2158721690
for (let k = 0; k < children.length; k++) {
2158821691
child = children[k];
21589-
if (child.typ != exports.EnumToken.NumberTokenType) {
21692+
if (child.typ != exports.EnumToken.NumberTokenType && child.typ != exports.EnumToken.PercentageTokenType) {
2159021693
return null;
2159121694
}
2159221695
values.push(getNumber(child));
@@ -21767,28 +21870,21 @@
2176721870
if (node.typ != exports.EnumToken.DeclarationNodeType || !node.nam.match(/^(-[a-z]+-)?transform$/)) {
2176821871
continue;
2176921872
}
21770-
const children = node.val.reduce((acc, curr) => {
21771-
if (curr.typ == exports.EnumToken.FunctionTokenType && 'skew' == curr.val.toLowerCase()) {
21772-
if (curr.chi.length == 3) {
21773-
if (curr.chi[2].val == 0) {
21774-
curr.chi.length = 1;
21775-
curr.val = 'skew';
21776-
}
21777-
else if (curr.chi[0].val == 0) {
21778-
curr.chi = [curr.chi[2]];
21779-
curr.val = 'skewY';
21780-
}
21781-
}
21782-
}
21783-
acc.push(curr);
21784-
return acc;
21785-
}, []);
21873+
const children = [];
21874+
for (const child of node.val) {
21875+
children.push(child.typ == exports.EnumToken.FunctionTokenType ? minifyTransformFunctions(child) : child);
21876+
}
2178621877
consumeWhitespace(children);
21787-
let { matrix, cumulative, minified } = compute(children) ?? {};
21878+
let { matrix, cumulative, minified } = compute(children) ?? {
21879+
matrix: null,
21880+
cumulative: null,
21881+
minified: null
21882+
};
2178821883
if (matrix == null || cumulative == null || minified == null) {
21884+
node.val = children;
2178921885
continue;
2179021886
}
21791-
let r = [filterValues(node.val.slice())];
21887+
let r = [filterValues(children)];
2179221888
if (eqMatrix(matrix, cumulative)) {
2179321889
r.push(cumulative);
2179421890
}

0 commit comments

Comments
 (0)