diff --git a/example/index.html b/example/index.html
index ccdf7c9..1b73df7 100644
--- a/example/index.html
+++ b/example/index.html
@@ -16,6 +16,14 @@
margin-bottom: 10px;
padding: 10px;
}
+ .section--transformed {
+ height: 50%;
+ transform:
+ scale(.5, 1)
+ translate(30px, 30%)
+ rotate(5deg)
+ skew(10deg, 30deg);
+ }
@@ -25,7 +33,7 @@
-
+
@@ -50,7 +58,9 @@
unit,
updateObject,
updateStyles,
- withEase
+ withEase,
+ getTransformStyle,
+ objectToFunctions
} = A
var $play = document.querySelector('.js-play')
@@ -58,6 +68,23 @@
var $back = document.querySelector('.js-back')
var $elastic = document.querySelector('.js-elastic')
var $elasticTarget = document.querySelector('.js-elastic-target')
+ var $transformed = document.querySelector('.section--transformed')
+
+ const transforms = getTransformStyle($transformed)
+ const transformsString = objectToFunctions(transforms)
+ const orginal = window.getComputedStyle($transformed, null).transform
+ let count = 0
+
+ setInterval(() => {
+ $transformed.style.transform = ((count + 1) % 2 === 0)
+ ? transformsString
+ : orginal
+
+ count++
+ }, 500)
+
+ console.log(transforms)
+ console.log(transformsString)
animate(
number(0, 350),
diff --git a/src/index.js b/src/index.js
index 6ebfc7d..7c0879a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -10,3 +10,7 @@ export { default as updateObject } from './update-object'
export { default as updateStyles } from './update-styles'
export { default as withEase } from './with-ease'
export { version } from '../package.json'
+export { default as decomposeMatrix } from './utils/decompose-matrix'
+export * from './utils/css-functions'
+export { default as getTransformStyle } from './utils/get-transform-style'
+export { default as setTransformStyle } from './utils/set-transform-style'
diff --git a/src/utils/css-functions.js b/src/utils/css-functions.js
new file mode 100644
index 0000000..cd3785a
--- /dev/null
+++ b/src/utils/css-functions.js
@@ -0,0 +1,29 @@
+const trim = (string) => string.trim()
+
+//
+// (scale, [1, 2]) -> 'scale(1,2)'
+//
+export const formatAsFunction = (name, value) => `${name}(${value})`
+
+//
+// { scale: [.5], translate: ['30px', '10px'], ... }
+// -> 'scale(.5) translate(30px,10px) ...'
+//
+export const objectToFunctions = (object) => Object.keys(object)
+ .map((key) => formatAsFunction(key, object[key]))
+ .join(' ')
+
+//
+// 'scale(.5) translate(30px, 10px) ...'
+// -> { scale: [.5], translate: ['30px', '10px'], ... }
+//
+export const functionsToObject = (string) => string
+ .replace(/[()]/g, '_')
+ .split('_')
+ .map(trim)
+ .filter(v => v !== '')
+ .reduce((resultObject, key, index, source) => {
+ if ((index + 1) % 2 === 0) return resultObject
+ resultObject[key] = source[index + 1].split(',').map(trim)
+ return resultObject
+ }, {})
diff --git a/src/utils/decompose-matrix.js b/src/utils/decompose-matrix.js
new file mode 100644
index 0000000..5416f7f
--- /dev/null
+++ b/src/utils/decompose-matrix.js
@@ -0,0 +1,48 @@
+// https://github.com/d3/d3-interpolate/blob/fb86fe51be75408141dbdcb4fa38a7ff1b8c76bd/src/transform/decompose.js
+
+const { atan, atan2, sqrt, PI } = Math
+const toDeg = (rad) => rad * (180 / PI)
+
+function decomposeMatrix (matrix) {
+ let [ a, b, c, d, e, f ] = matrix.map(v => Number(v))
+
+ let scaleX = sqrt(a * a + b * b)
+ if (scaleX) {
+ a /= scaleX
+ b /= scaleX
+ }
+
+ let skewX = a * c + b * d
+ if (skewX) {
+ c -= a * skewX
+ d -= b * skewX
+ }
+
+ let scaleY = sqrt(c * c + d * d)
+ if (scaleY) {
+ c /= scaleY
+ d /= scaleY
+ skewX /= scaleY
+ }
+
+ if (a * d < b * c) {
+ a = -a
+ b = -b
+ skewX = -skewX
+ scaleX = -scaleX
+ }
+
+ const rotationDeg = toDeg(atan2(b, a))
+ const skewDeg = toDeg(atan(skewX))
+
+ return {
+ translateX: e + 'px',
+ translateY: f + 'px',
+ rotate: rotationDeg + 'deg',
+ skew: skewDeg + 'deg',
+ scaleX: scaleX,
+ scaleY: scaleY
+ }
+}
+
+export default decomposeMatrix
diff --git a/src/utils/get-style.js b/src/utils/get-style.js
index 126607e..02c4818 100644
--- a/src/utils/get-style.js
+++ b/src/utils/get-style.js
@@ -1,8 +1,8 @@
import kebab from './kebab'
-const getStyle = (el, prop) => {
- if (prop in el.style) {
- return window.getComputedStyle(el)[kebab(prop)] || 0
+const getStyle = ($el, prop) => {
+ if (prop in $el.style) {
+ return window.getComputedStyle($el, null)[kebab(prop)] || 0
}
}
diff --git a/src/utils/get-transform-style.js b/src/utils/get-transform-style.js
new file mode 100644
index 0000000..1a6ff80
--- /dev/null
+++ b/src/utils/get-transform-style.js
@@ -0,0 +1,12 @@
+import decomposeMatrix from './decompose-matrix'
+import { functionsToObject } from './css-functions'
+import getStyle from './get-style'
+
+const getTransformStyle = ($el) => {
+ const value = getStyle($el, 'transform')
+ const { matrix, matrix3d } = functionsToObject(value)
+ if (!matrix && !matrix3d) return ''
+ return decomposeMatrix(matrix || matrix3d)
+}
+
+export default getTransformStyle
diff --git a/src/utils/set-style.js b/src/utils/set-style.js
index 2a9539e..a5236e9 100644
--- a/src/utils/set-style.js
+++ b/src/utils/set-style.js
@@ -1,5 +1,5 @@
-const setStyle = (el, prop, value) => {
- el.style[prop] = value
+const setStyle = ($el, prop, value) => {
+ $el.style[prop] = value
}
export default setStyle
diff --git a/src/utils/set-transform-style.js b/src/utils/set-transform-style.js
new file mode 100644
index 0000000..c0d1fb5
--- /dev/null
+++ b/src/utils/set-transform-style.js
@@ -0,0 +1,32 @@
+import setStyle from './set-style'
+
+const TRANSFORM_KEY = 'transform'
+
+const INITITAL_TRANSFORM = {
+ rotate: '0deg',
+ rotateX: '0deg',
+ rotateY: '0deg',
+ rotateZ: '0deg',
+ skewX: '0deg',
+ skewY: '0deg',
+ scale: 1,
+ scaleX: 1,
+ scaleY: 1,
+ scaleZ: 1,
+ translate: 0,
+ translateX: 0,
+ translateY: 0,
+ translateZ: 0
+}
+
+const TRANSFORM_PROPS = Object.keys(INITITAL_TRANSFORM)
+
+export const isTransformProp = (prop) => (TRANSFORM_PROPS.indexOf(prop) !== -1)
+
+export const setTransformStyle = ($el, value, key = TRANSFORM_KEY) => {
+ const stringValue = value
+
+ setStyle($el, key, stringValue)
+}
+
+export default setTransformStyle