How to Read/Parse Individual Transform Style Values in JavaScript

How to get value translateX by javascript

You can use Window.getComputedStyle()

var myElement = document.querySelector('.hello');
// set inline-style transform to element
myElement.style.transform = "translateX(" + (-200) + "px) scaleX(" + 1.6 + ") scaleY(" + 1.2 + ")";

function getTranslateX() {
var style = window.getComputedStyle(myElement);
var matrix = new WebKitCSSMatrix(style.transform);
console.log('translateX: ', matrix.m41);
}

document.querySelector('button').addEventListener('click', getTranslateX);
.hello {
height: 100px;
width: 100px;
background: orange;
}
<div class="hello"></div>
<button type="button">get value</button>

How to set a single value of transform while leaving the other values?

There is no way to directly modify a single component of the transform. Sadly, the various possible transforms were implemented as values on the transform attribute, rather than attributes themselves. There is no object model for CSS attribute values - attribute values are always just a string, as far as JavaScript is concerned. It would've been nice if transform was treated as a shorthand attribute for, eg, transform-rotate-y, transform-*, etc, the same way that background is a shorthand attribute for all the background-* attributes. This would've allowed us direct access to the values via JavaScript, but it was not implemented that way, so we are out of luck.

Edit: The simplest way to accomplish this (without studying the spec and doing a bunch of math) would be to nest your elements, applying different transformations to each. If you apply several transformations that won't change, go ahead and combine those on to one element. Any transformation that you do want to change, use a separate element:

Works here: jsfiddle.net/mkTKH/15


Edit: My original solution below won't work. In testing it out I discovered that getComputedStyle() converts the transform into a matrix(). An early draft of the spec says:

The transform property of the style object returned by getComputedStyle contains a single CSSTransformValue with a type of CSS_MATRIX. The 6 parameters represent the 3x2 matrix that is the result of applying the individual functions listed in the transform property.


So, you have to parse it. If you want to change just one portion of an attribute value, you can use a regular expression to parse the value:

var rotateY = "rotateY(" + deg + "deg)";
var transform = el.style.webkitTransform.replace(/\brotateY([^)]+)\b/, rotateY);
el.style.webkitTransform = transform;

I'd create a reusable function:

function setTransformValue(el, name, value) {
var currentValue = new RegExp(name + "([^)]+)");
var style = window.getComputedStyle ? getComputedStyle(el) : el.currentStyle;
var currentTransform = style.transform ||
style.webkitTransform ||
style.MozTransform ||
style.msTransform ||
style.OTransform;
var transform;
if (currentValue.test(currentTransform )) {
transform = currentTransform.replace(currentValue, name + "(" + value + ")");
}
else {
transform = currentTransform + " " + name + "(" + value + ")";
}
el.style.transform = transform;
}

Untested.

Regular Expression (Regex) on CSS3 Transform String

If you absolutely must use regular expression to do this, you can use the exec() method in a loop, pushing the match result of the captured group(s) to the desired arrays of choice.

var str = 'translateX(-50%) scale(1.2)'
var re = /(\w+)\(([^)]*)\)/g,
names = [], vals = [];

while (m = re.exec(str)) {
names.push(m[1]), vals.push(m[2]);
}

console.log(names) //=> [ 'translateX', 'scale' ]
console.log(vals) //=> [ '-50%', '1.2' ]

The regular expression uses two capture groups, the first matches/captures word characters only, the second uses negation which will match any character except ) "zero or more" times.

How to convert CSS transform matrix back to its component properties

Yes, it's possible to do that!

The parameters to matrix come in this order:
matrix(scaleX(),skewY(),skewX(),scaleY(),translateX(),translateY())

Read more about it here

If you want to retrieve the numbers from that string (matrix(1,0,0,1,720,290) you could use this regex:

style = window.getComputedStyle(elem1, null);
trans = style.transform;
numberPattern = /-?\d+\.?\d*/g;

values = trans.match( numberPattern );

This will return the following array:

["1", "0", "0", "1", "720", "290"]

Edit after comments

The values returned in the window.getComputedStyle are the computed values (i.e. the percentages you used are being parsed to pixel values). You can reverse that calculation, but you need to know what the percentage is using to figure out how many pixels it should be.

Enter CSS3 Transforms


One interesting thing about CSS transforms is that, when applying them with percentage values, they base that value on the dimensions of the element which they are being implemented on, as opposed to properties like top, right, bottom, left, margin, and padding, which only use the parent's dimensions (or in case of absolute positioning, which uses its closest relative parent).
Source

if you use the following calculation, you should be able to get the percentages you used:

style = window.getComputedStyle(elem1, null);
trans = style.transform;
numberPattern = /-?\d+\.?\d+|\d+/g;

values = trans.match( numberPattern );

computedTranslateX = values[4];
computedTranslatey = values[5];

xPercentage = (computedTranslateX / elem1.offsetWidth) * 100;
yPercentage = (computedTranslateY / elem1.offsetHeight) * 100;

How to exact set a dynamic style transform using Javascript?

Note: you should use skewX and/or skewY instead of skew. See the MDN info here.

It would be easier to keep track of the transforms in a variable:

var elRot,    // the rotation 'counter' for the element 'el'
elScale, // the scale 'counter' for the element 'el'
elSkewX, // the skewX 'counter' for the element 'el'
elSkewY; // the skewY 'counter' for the element 'el'

// initialize values
elRot = 0;
elScale = 1;
elSkewX = 0;
elSkewY = 0;

or an object:

var elTranform = {
rot: 0, // the rotation 'counter' for the element 'el'
sca: 1, // the scale 'counter' for the element 'el'
skx: 0, // the skewX 'counter' for the element 'el'
sky: 0 // the skewY 'counter' for the element 'el'
};

So now you can start with the function (you will still use var el for the element), the first step is getting the values, so you change the arguments given to the function:

// use this with separate vars
function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
// how to write some code to set the el transform style...
}

// use this with the object
function setTransform (element, elTransformArg) {
// how to write some code to set the el transform style...
}

Next you have re-specify any other transforms that are 'staying', in the example you give, the skewX remains 45deg:

function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
// the brackets cause the string to be evaluated before being assigned
element.style.transform = ("rotate() scale() skewX() skewY()");
}

or

function setTransform (element, elTransformArg) {
element.style.transform = ("rotate() scale() skewX() skewY()");
}

Now you have to put the arguments into the string:

function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
element.style.transform = ("rotate(" + rotationArg + "deg ) scale(" + scaleArg
+ ") skewX(" + skewXArg + "deg ) skewY(" + skewYArg + "deg )");
}

or

function setTransform (element, elTransformArg) {
element.style.transform = ("rotate(" + elTransformArg.rot + "deg ) scale("
+ elTransformArg.sca + ") skewX(" + elTransformArg.skx + "deg ) skewY("
+ elTransformArg.sky + "deg )");
}

A bit messy, so put that string in a variable (this will be beneficial for the prefixes):

function setTransform (element, rotationArg, scaleArg, skewXArg, skewYArg) {
var transformString = ("rotate(" + rotationArg + "deg ) scale(" + scaleArg
+ ") skewX(" + skewXArg + "deg ) skewY(" + skewYArg + "deg )");

// now attach that variable to each prefixed style
element.style.webkitTransform = transformString;
element.style.MozTransform = transformString;
element.style.msTransform = transformString;
element.style.OTransform = transformString;
element.style.transform = transformString;
}

or

function setTransform (element, elTransformArg) {
var transformString= ("rotate(" + elTransformArg.rot + "deg ) scale("
+ elTransformArg.sca + ") skewX(" + elTransformArg.skx + "deg ) skewY("
+ elTransformArg.sky + "deg )");

// now attach that variable to each prefixed style
element.style.webkitTransform = transformString;
element.style.MozTransform = transformString;
element.style.msTransform = transformString;
element.style.OTransform = transformString;
element.style.transform = transformString;
}

Now call the function:

setTransform(el, elRot, elScale, elSkewX, elSkewY);

or

setTransform(el, elTransform);

To change values, change the variables or object values and call:

elRot = 45;
elSkewX = 30;
setTransform(el, elRot, elScale, elSkewX, elSkewY);

or

elTransform.rot = 45;
elTransform.skx = 30;
setTransform(el, elTransform);

This way you only have to change the 'counter' values for each transform, and call the function to apply the transform. As mentioned above, it is important to keep any transforms that are not changed as this simply replaces the previous CSS value for the transform with the new one. Giving multiple values means only the last one is used (the C part of CSS).

Combine css3 transforms via js

You need to manipulate the matrix in order do accomplish what you want to do:

   var transform = new  WebKitCSSMatrix(window.getComputedStyle(element).webkitTransform);
transform = transform.rotateAxisAngle(0,0,0,45)
element.style.webkitTransform = transform;

The methods for manipulating WebkitCSSMatrix are:

.multiply()
.inverse()
.translate()
.scale()
.rotate()
.rotateAxisAngle()
.skewX()
.skewY()

And you can view a demo here:

http://jsfiddle.net/6jGaA/

Get translate3d values of a div?

The value gets stored either as a matrix or a matrix3d, depending on whether or not the z value was set. Assuming no other transformations, for a 2D matrix, X and Y are the last two values. For a 3D matrix, X, Y, Z, 1 are the last four digits.

You could use a regular expression to get the values:

function getTransform(el) {
var results = $(el).css('-webkit-transform').match(/matrix(?:(3d)\(\d+(?:, \d+)*(?:, (\d+))(?:, (\d+))(?:, (\d+)), \d+\)|\(\d+(?:, \d+)*(?:, (\d+))(?:, (\d+))\))/)

if(!results) return [0, 0, 0];
if(results[1] == '3d') return results.slice(2,5);

results.push(0);
return results.slice(5, 8);
}


Related Topics



Leave a reply



Submit