42

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?

traktor
  • 17,588
  • 4
  • 32
  • 53
einstein
  • 13,389
  • 27
  • 80
  • 110

7 Answers7

105

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.

Joel
  • 15,496
  • 7
  • 52
  • 40
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?

Lea Verou
  • 23,618
  • 9
  • 46
  • 48
  • +1 for making me realize that the game ain't worth the candle. I have to do something simpler before I go mad. ^_^ – Robusto Jul 23 '15 at 13:08
  • 2
    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*)\)/` – Massale Feb 25 '17 at 11:13
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/

methodofaction
  • 70,885
  • 21
  • 151
  • 164
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.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
  • 1
    I believe you have an extra "matrix" in line 3. Should be var matrixArray = matrix.replace("matrix(", "").split(","); – colin moock Oct 11 '19 at 03:21
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.

caiocpricci2
  • 7,714
  • 10
  • 56
  • 88
2

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.

Ybochatay
  • 46
  • 3
  • 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 }`. – Marcelo Barros Jan 30 '23 at 16:42
0

Using regex

element.style.transform.match(/scale\(([1-9\.])\)/)[1]
Daniel Garcia
  • 462
  • 3
  • 8