From 8a8e7cfe22756e876606940d1acfd33044cbb64b Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 26 Feb 2016 13:37:38 -0800 Subject: [PATCH] Slightly cleaner. --- src/transform/decompose.js | 52 +++++++++++++++++++------------------- src/transform/index.js | 48 +++++++++++++++++------------------ src/transform/parse.js | 16 ++++++------ 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/src/transform/decompose.js b/src/transform/decompose.js index 1f4d962..00f7523 100644 --- a/src/transform/decompose.js +++ b/src/transform/decompose.js @@ -1,34 +1,34 @@ var rad2deg = 180 / Math.PI; -export default function(matrix) { - var r0 = [matrix.a, matrix.b], - r1 = [matrix.c, matrix.d], - kx = normalize(r0), - kz = dot(r0, r1), - ky = normalize(combine(r1, r0, -kz)) || 0; +export var identity = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 +}; - if (r0[0] * r1[1] < r1[0] * r0[1]) r0[0] *= -1, r0[1] *= -1, kx *= -1, kz *= -1; +export default function(a, b, c, d, e, f) { + if (a * d === b * c) return null; - return { - rotate: (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * rad2deg, - translate: [matrix.e, matrix.f], - scale: [kx, ky], - skew: ky ? Math.atan2(kz, ky) * rad2deg : 0 - }; -} + var scaleX = Math.sqrt(a * a + b * b); + a /= scaleX, b /= scaleX; -function dot(a, b) { - return a[0] * b[0] + a[1] * b[1]; -} + var skewX = a * c + b * d; + c -= a * skewX, d -= b * skewX; -function normalize(a) { - var k = Math.sqrt(dot(a, a)); - if (k) a[0] /= k, a[1] /= k; - return k; -} + var scaleY = Math.sqrt(c * c + d * d); + c /= scaleY, d /= scaleY, skewX /= scaleY; + + if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; -function combine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * rad2deg, + skewX: Math.atan(skewX) * rad2deg, + scaleX: scaleX, + scaleY: scaleY + }; } diff --git a/src/transform/index.js b/src/transform/index.js index 8c56dc7..d05ccc6 100644 --- a/src/transform/index.js +++ b/src/transform/index.js @@ -7,38 +7,38 @@ function interpolateTransform(parse, pxComma, pxParen, degParen) { return s.length ? s.pop() + " " : ""; } - function translate(ta, tb, s, q) { - if (ta[0] !== tb[0] || ta[1] !== tb[1]) { + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { var i = s.push("translate(", null, pxComma, null, pxParen); - q.push({i: i - 4, x: number(ta[0], tb[0])}, {i: i - 2, x: number(ta[1], tb[1])}); - } else if (tb[0] || tb[1]) { - s.push("translate(" + tb[0] + pxComma + tb[1] + pxParen); + q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); } } - function rotate(ra, rb, s, q) { - if (ra !== rb) { - if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; // shortest path - q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number(ra, rb)}); - } else if (rb) { - s.push(pop(s) + "rotate(" + rb + degParen); + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); } } - function skew(wa, wb, s, q) { - if (wa !== wb) { - q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(wa, wb)}); - } else if (wb) { - s.push(pop(s) + "skewX(" + wb + degParen); + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); } } - function scale(ka, kb, s, q) { - if (ka[0] !== kb[0] || ka[1] !== kb[1]) { + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { var i = s.push(pop(s) + "scale(", null, ",", null, ")"); - q.push({i: i - 4, x: number(ka[0], kb[0])}, {i: i - 2, x: number(ka[1], kb[1])}); - } else if (kb[0] !== 1 || kb[1] !== 1) { - s.push(pop(s) + "scale(" + kb + ")"); + q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); } } @@ -46,10 +46,10 @@ function interpolateTransform(parse, pxComma, pxParen, degParen) { var s = [], // string constants and placeholders q = []; // number interpolators a = parse(a), b = parse(b); - translate(a.translate, b.translate, s, q); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); rotate(a.rotate, b.rotate, s, q); - skew(a.skew, b.skew, s, q); - scale(a.scale, b.scale, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); a = b = null; // gc return function(t) { var i = -1, n = q.length, o; diff --git a/src/transform/parse.js b/src/transform/parse.js index 67c4f70..87f256b 100644 --- a/src/transform/parse.js +++ b/src/transform/parse.js @@ -1,24 +1,24 @@ -import decompose from "./decompose"; +import decompose, {identity} from "./decompose"; -var identity = {a: 1, b: 0, c: 0, d: 1, e: 0, f: 0}, - cssNode, +var cssNode, cssRoot, cssView, svgNode; export function parseCss(value) { - if (value === "none") return decompose(identity); + if (value === "none") return identity; if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; cssNode.style.transform = value; cssRoot.appendChild(cssNode); value = cssView.getComputedStyle(cssNode, null).getPropertyValue("transform"); cssRoot.removeChild(cssNode); var m = value.slice(7, -1).split(","); - return decompose({a: +m[0], b: +m[1], c: +m[2], d: +m[3], e: +m[4], f: +m[5]}); -}; + return decompose(+m[0], +m[1], +m[2], +m[3], +m[4], +m[5]); +} export function parseSvg(value) { if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); svgNode.setAttribute("transform", value == null ? "" : value); - return decompose(svgNode.transform.baseVal.consolidate().matrix); -}; + var m = svgNode.transform.baseVal.consolidate().matrix; + return decompose(m.a, m.b, m.c, m.d, m.e, m.f); +}