47

I'm wondering how I can get the scale value of an element?

I have tried $(element).css('-webkit-transform'); which returns matrix(scaleX,0,0,scaleY,0,0); Is there a way of getting scaleX and scaleY only?

0

7 Answers 7

110

The simplest solution to find out the scale factor between the document and an element is the following:

var element = document.querySelector('...');
var scaleX = element.getBoundingClientRect().width / element.offsetWidth;

This works because getBoundingClientRect returns the actual dimension while offsetWidth/Height is the unscaled size.

Sign up to request clarification or add additional context in comments.

5 Comments

Great answer. It works fine on Chrome, and the MDN site suggests that it will work on IE9+ - developer.mozilla.org/en-US/docs/Web/API/Element/…
Great answer. I didn't know getBoundingClientRect would get the actual scaled size.
In iOS Webview element.getBoundingClientRect().width does not return scaled width, just the normal width. I used window.screen.width instead.
Would this work if you rotated the element?
@AndyS no it wouldn't work in that case
27

If it was specified by a matrix I guess you can't with a straightforward way, but you can easily parse the value:

var matrixRegex = /matrix\((-?\d*\.?\d+),\s*0,\s*0,\s*(-?\d*\.?\d+),\s*0,\s*0\)/,
    matches = $(element).css('-webkit-transform').match(matrixRegex);

matches[1] will contain scaleX and matches[2] will contain scaleY. If it's possible that other transformations have also been applied, you'd need to slightly tweak the regex, because now it assumes that all other parameters are 0.

A way to just get the scale values might be to remove any transforms, measure the computed width/height of the element and then add them back and measure again. Then divide new/old values. Haven't tried it, but it might work. jQuery itself uses a similar approach for many measurements, it even has an undocumented $.swap() function just for this.

PS: You are using -o-transform -moz-transform and -ms-transform too, right?

2 Comments

+1 for making me realize that the game ain't worth the candle. I have to do something simpler before I go mad. ^_^
If other parameters aren't 0, you we can use matrixRegex = /matrix\(\s*(-?\d*\.?\d*),\s*(-?\d*\.?\d*),\s*(-?\d*\.?\d*),\s*(-?\d*\.?\d*),\s*(-?\d*\.?\d*),\s*(-?\d*\.?\d*)\)/
9

If you need to target webkit only (because it's for the iPhone, or iPad) the most reliable and fast way is using the native javascript webkit provides:

node = $("#yourid")[0];
var curTransform = new WebKitCSSMatrix(window.getComputedStyle(node).webkitTransform);
alert(curTransform.a); // curTransform is an object,
alert(curTransform.d); // a through f represent all values of the transformation matrix

You can view a demo here: http://jsfiddle.net/umZHA/

Comments

6

You could use the following:

var element = document.getElementById("elementID");
// returns matrix(1,0,0,1,0,0)
var matrix = window.getComputedStyle(element).transform;
var matrixArray = matrix.replace("matrix(", "").split(",");
var scaleX = parseFloat(matrixArray[0]); // convert from string to number
var scaleY = parseFloat(matrixArray[3]);
// bonus round - gets translate values
var translateX = parseFloat(matrixArray[4]); 
var translateY = parseFloat(matrixArray[5]); // parseFloat ignores ")"

1 Comment

I believe you have an extra "matrix" in line 3. Should be var matrixArray = matrix.replace("matrix(", "").split(",");
3

A more robust and generic way to get the scale :

const { width, height } = element.getBoundingClientRect()
const scale = { x : element.offsetWidth / width, y : element.offsetHeight / height }

It compares the visual dimensions with the non-scaled dimensions. So it will work even with nested scaled elements.

3 Comments

Interesting. It's worth mentioning that, to return the same value used as the scale, it'd be interesting to invert the division. const scale = { x : width / element.offsetWidth, y : element / node.offsetHeight }.
Interesting. When I calculate these values for an image with height and width constrained by max-height and max-width (to fit the whole image on the screen with preserved aspect ratio), the offset* numbers and the GetBoundingClientRect are just about the same numbers, the latter being the next larger integer. That doesn't tell me how much the image is scaled, which I would love to know!
In your case @Victoria you should not use offsetWidth/offsetHeight but naturalWidth and naturalHeight.
2

Too late for the OP but might be useful in the future. There is a straightforward way to do it using splits:

function getTransformValue(element,property){       
        var values = element[0].style.webkitTransform.split(")");
        for (var key in values){
            var val = values[key];              
            var prop = val.split("(");          
            if (prop[0].trim() == property)
                return prop[1];
        }                   
        return false;           
    }

This is webkit specific, but can easily be extended for more browsers modifying the fist line.

Comments

1

Using regex

element.style.transform.match(/scale\(([1-9\.])\)/)[1]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.