52

I have CSS style for a layer:

.element {
    -webkit-transform: rotate(7.5deg);    
     -moz-transform: rotate(7.5deg);    
      -ms-transform: rotate(7.5deg);    
       -o-transform: rotate(7.5deg);   
          transform: rotate(7.5deg);
}

Is there a way to get curent rotation value through jQuery?

I tried this

$('.element').css("-moz-transform")

The result is matrix(0.991445, 0.130526, -0.130526, 0.991445, 0px, 0px) which doesn't tell me a lot. What I'm looking to get is 7.5.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
Goldie
  • 1,570
  • 5
  • 21
  • 33
  • `matrix()` is showing the transform data but you will need to find out what each parameter does and do the math yourself – J V Nov 25 '11 at 15:16
  • Thanx. I'm meanwhile I found out what is matrix and I what values it changes when i change rotate value //matrix(1, 0, 0, 1, 0px, 0px) //rotation 0 deg I still can't figure it out how to get rotation value matrix(0.984808, 0.173648, -0.173648, 0.984808, 0px, 0px) //rotation 10 deg matrix(0.939693, 0.34202, -0.34202, 0.939693, 0px, 0px) //rotation 20 deg – Goldie Nov 25 '11 at 15:23
  • 4
    why not keep the value mirrored e.g. in a data attribute? – schellmax Dec 06 '12 at 10:48
  • If you'd ever need for a pure JS solution, please have a look at https://stackoverflow.com/a/54492696/1078556 – danicotra Feb 02 '19 at 11:46

11 Answers11

100

Here's my solution using jQuery.

This returns a numerical value corresponding to the rotation applied to any HTML element.

function getRotationDegrees(obj) {
    var matrix = obj.css("-webkit-transform") ||
    obj.css("-moz-transform")    ||
    obj.css("-ms-transform")     ||
    obj.css("-o-transform")      ||
    obj.css("transform");
    if(matrix !== 'none') {
        var values = matrix.split('(')[1].split(')')[0].split(',');
        var a = values[0];
        var b = values[1];
        var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
    } else { var angle = 0; }
    return (angle < 0) ? angle + 360 : angle;
}

angle1 = getRotationDegrees($('#myDiv'));
angle2 = getRotationDegrees($('.mySpan a:last-child'));

etc...

TwystO
  • 2,456
  • 2
  • 22
  • 28
  • The `+=` operator in the `return` statement can be replaced with `+` as the assignment won't affect the returned value. – Asbjørn Ulsberg Jan 21 '15 at 13:19
  • It doesn't work with `rotate3d` or `rotateX` values ? https://jsfiddle.net/k35o1s27/1/ – Alvaro Oct 04 '16 at 09:49
  • 1
    Beware that if the element is invisible (inside another element that has `display:none`) the transform will always return value `none` and this function will return rotation 0 – Kyborek Jun 05 '17 at 09:54
11

I've found a bug/features in the Twist's code: the function return negative angles.

So I've add a simple line of code before returning the angle:

if(angle < 0) angle +=360;

Than the results will be:

function getRotationDegrees(obj) {
    var matrix = obj.css("-webkit-transform") ||
    obj.css("-moz-transform")    ||
    obj.css("-ms-transform")     ||
    obj.css("-o-transform")      ||
    obj.css("transform");
    if(matrix !== 'none') {
        var values = matrix.split('(')[1].split(')')[0].split(',');
        var a = values[0];
        var b = values[1];
        var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
    } else { var angle = 0; }

    if(angle < 0) angle +=360;
    return angle;
}
andreacanton
  • 383
  • 3
  • 11
  • 2
    I gained the Necromancer badge today... and corrected my code with your bugfix :) Thanks you to notice the negative angles possibility. – TwystO May 12 '13 at 16:06
  • 2
    You should change that `if(angle < 0)` to `while(angle < 0)`, so that angles less than `-360` continue to get processed until they become positive. – Benjam Oct 29 '13 at 20:20
8

My Solution (using jQuery):

$.fn.rotationInfo = function() {
    var el = $(this),
        tr = el.css("-webkit-transform") || el.css("-moz-transform") || el.css("-ms-transform") || el.css("-o-transform") || '',
        info = {rad: 0, deg: 0};
    if (tr = tr.match('matrix\\((.*)\\)')) {
        tr = tr[1].split(',');
        if(typeof tr[0] != 'undefined' && typeof tr[1] != 'undefined') {
            info.rad = Math.atan2(tr[1], tr[0]);
            info.deg = parseFloat((info.rad * 180 / Math.PI).toFixed(1));
        }
    }
    return info;
};

Usage:

$(element).rotationInfo(); // {deg: 7.5, rad: 0.13089969389957515}
$(element).rotationInfo().deg; // 7.5
Pigalev Pavel
  • 1,155
  • 1
  • 15
  • 29
  • Kudos for making it a jQuery function, making it concise and showing usage examples! Thanks. also for returning floats of both radians and degrees. For those reasons, this is the solution I'll use. – clearlight Dec 15 '15 at 13:38
6

Here is a plug-in version of Twist's function. Also, the conditional if(matrix !== 'none') did not work for me. So I have added type-checking:

(function ($) {
    $.fn.rotationDegrees = function () {
         var matrix = this.css("-webkit-transform") ||
    this.css("-moz-transform")    ||
    this.css("-ms-transform")     ||
    this.css("-o-transform")      ||
    this.css("transform");
    if(typeof matrix === 'string' && matrix !== 'none') {
        var values = matrix.split('(')[1].split(')')[0].split(',');
        var a = values[0];
        var b = values[1];
        var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
    } else { var angle = 0; }
    return angle;
   };
}(jQuery));

Use as follows:

var rotation = $('img').rotationDegrees();
Ivo Renkema
  • 2,188
  • 1
  • 29
  • 40
4

The CSS tranform property will always return a matrix value, as rotate, skew, scale etc. is just shorthand for doing things easier, and not having to calculate the matrix value everytime, however the matrix is calculated by the browser and applied as a matrix, and when that is done it can no longer return the rotated degree by angle without recalculating the matrix back again.

To make such calcualtions easier there is a javascript library called Sylvester that was created for the purpose of easy matrix calculation, try looking at that to get the rotation degree from the matrix value.

Also, if you where to write a rotate function in javascript to translate rotational degrees to a matrix, it would probably look something like this (this uses sylvester for the last calculation) :

var Transform = {
    rotate: function(deg) {
        var rad = parseFloat(deg) * (Math.PI/180),
            cos_theta = Math.cos(rad),
            sin_theta = Math.sin(rad);

        var a = cos_theta,
            b = sin_theta,
            c = -sin_theta,
            d = cos_theta;

        return $M([
          [a, c, 0],
          [b, d, 0],
          [0, 0, 1]
        ]);
    }
};

Now all you really have to do is reverse enginer that function and you're golden :-)

alex
  • 479,566
  • 201
  • 878
  • 984
adeneo
  • 312,895
  • 29
  • 395
  • 388
2

I have make a fiddle with this working code to get rotateX Y Z on a 3D , or rotateZ for a 2D transform. Thanks to mihn for the base code that i have little updated with actual jquery 2.2.3. I currently use this solution for my own projects.

https://jsfiddle.net/bragon95/49a4h6e9/

    //
//Thanks: Adapted on base code from mihn http://stackoverflow.com/a/20371725
//

function getcsstransform(obj)
{
    var isIE = /(MSIE|Trident\/|Edge\/)/i.test(navigator.userAgent);

  var TType="undefined",
        rotateX = 0,
        rotateY = 0,
      rotateZ = 0;

  var matrix = obj.css("-webkit-transform") ||
    obj.css("-moz-transform") ||
    obj.css("-ms-transform") ||
    obj.css("-o-transform") ||
    obj.css("transform");
  if (matrix!==undefined && matrix !== 'none')
  {
        // if matrix is 2d matrix
    TType="2D";
    if (matrix.indexOf('matrix(') >= 0)
    {
      var values = matrix.split('(')[1].split(')')[0];
      if (isIE)  //case IE
      {
        angle = parseFloat(values.replace('deg', STR_EMPTY));
      }else
      {
        values = values.split(',');
        var a = values[0];
        var b = values[1];
        var rotateZ = Math.round(Math.atan2(b, a) * (180 / Math.PI));
      }
    }else
    {
      // matrix is matrix3d
      TType="3D";
      var values = matrix.split('(')[1].split(')')[0].split(',');
      var sinB = parseFloat(values[8]);
      var b = Math.round(Math.asin(sinB) * 180 / Math.PI);
      var cosB = Math.cos(b * Math.PI / 180);
      var matrixVal10 = parseFloat(values[9]);
      var a = Math.round(Math.asin(-matrixVal10 / cosB) * 180 / Math.PI);
      var matrixVal1 = parseFloat(values[0]);
      var c = Math.round(Math.acos(matrixVal1 / cosB) * 180 / Math.PI);
      rotateX = a;
      rotateY = b;
      rotateZ = c;
    }
  }

    return  { TType: TType, rotateX: rotateX,  rotateY: rotateY,  rotateZ: rotateZ };
};

mAngle = getcsstransform($("#Objet3D"));
if (mAngle.TType=="2D")
{
    $("#Result").html("Transform 2D [rotateZ=" + mAngle.rotateZ + "&deg;]");
}else
{
    $("#Result").html("Transform 3D [rotateX=" + mAngle.rotateX + "&deg;|rotateY=" + mAngle.rotateY + "&deg;|rotateZ=" + mAngle.rotateZ + "&deg;]");
}
Bragon95
  • 21
  • 3
  • 2
    Please don't add "thanks" as answers. Invest some time in the site and you will gain sufficient [privileges](//stackoverflow.com/privileges) to upvote answers you like, which is the Stack Overflow way of saying thank you. – Bhargav Rao Jun 09 '16 at 11:55
2

This script is very helpful https://github.com/zachstronaut/jquery-css-transform

Goldie
  • 1,570
  • 5
  • 21
  • 33
  • 1
    Much Better Solution Than Accepted. +1. This thing even works to retrieve degrees when set the other way. – Mike_K Apr 17 '12 at 19:02
0

If you do this in the way you described, any this is the only place where you actually modify transform of the object, then since your browser can not be all 4 kinds of browsers at the same time, some of the prefixed values you assigned are still exactly as you assigned them. So for example if you use webkit, then this.css('-o-transform') will still return 'rotate(7.5deg)', so it is just a matter of matching it against /rotate\((.*)deg\)/.

This worked fine for me : I always assign 5 css styles, and read back all five styles, hoping that at least one of them will be untouched. I am not sure if this works if the styles are set in CSS (not in JS) though.

qbolec
  • 5,374
  • 2
  • 35
  • 44
0

Also you could replace var angle = Math.round(Math.atan2(b, a) * (180/Math.PI)); to var angle = Math.round(Math.acos(a) * (180/Math.PI));

0

Since I constantly need to use jQuery together with TweenMax and since TweenMax already took care of all the parsing of various types of transformation strings as well as compatibility issues, I wrote a tiny jquery plugin here (more of a wrap up of gsap's) that could directly access these values like this:

$('#ele').transform('rotationX') // returns 0
$('#ele').transform('x')         // returns value of translate-x

The list of properties you could get/set, along with their initial properties:

perspective: 0
rotation: 0
rotationX: 0
rotationY: 0
scaleX: 1
scaleY: 1
scaleZ: 1
skewX: 0
skewY: 0
x: 0
y: 0
z: 0
zOrigin: 0

Paste from my other answer, hope this helps.

Lucia
  • 13,033
  • 6
  • 44
  • 50
0

If you're willing to use in-line styling for just this transformation, then you can use jQuery to get the contents of the style tag:

parseInt($(  /*TODO*/  ).attr('style').split('rotate(')[1].split('deg)')[0]);
Jake6192
  • 13
  • 5