3

Having an element with the following transformation:

style="transform: rotate3d(1, 0, 0, -50deg);"

I want to be able to get the value -50 with Javascript/jQuery. I want to get the absolute value, so if it is 370deg, i do not want to get 10, but 370.

Using $('#element').css('transform') returns a matrix like this:

matrix3d(1, 0, 0, 0, 0, 0.642788, -0.766044, 0, 0, 0.766044, 0.642788, 0, 0, 0, 0, 1)

Which can be better represented as:

matrix3d(
    1, 0, 0, 0, 
    0, 0.642788, -0.766044, 0, 
    0, 0.766044, 0.642788, 0,
    0, 0, 0, 1
)

Is solving the equations the only way to get this value?

enter image description here

Knowing that Z =0 and X =1 as rotate3d(1, 0, 0, -50deg);

enter image description here

Isn't there any faster alternative to this?

Community
  • 1
  • 1
Alvaro
  • 40,778
  • 30
  • 164
  • 336
  • How is the value being set in the first place? Could you simply keep track of it? – Matt Way Oct 04 '16 at 12:22
  • I'm using css3 transitions. So nop, it can not get tracked during the animation. Thus the question :) – Alvaro Oct 04 '16 at 12:24
  • paper.js has some good functions to handle this, but I would love to hear about some native solutions as well ... http://paperjs.org/reference/matrix/ – rafaelcastrocouto Oct 04 '16 at 12:37

3 Answers3

2

While it still requires calculations ran on the matrix values, the simplest example I could find is as follows:

var el = document.getElementById('test');
var st = window.getComputedStyle(el, null);
var m = st.getPropertyValue('transform');

var values = m.slice(7,-1).split(',');
// angle is in range -180 > 180
var angle = Math.round(Math.atan2(values[1], values[0]) * (180/Math.PI));

Fiddle here. More info here.


Note: The example given was tested on a matrix rather than matrix3d. However from MDN:

matrix(a, b, c, d, tx, ty) is a shorthand for matrix3d(a, b, 0, 0, c, d, 0, 0, 0, 0, 1, 0, tx, ty, 0, 1)

So you can apply the exact same method to solve in either case, you will just need to update the method for pulling out the values.

Matt Way
  • 32,319
  • 10
  • 79
  • 85
  • Did you notice that the matrix returned by st.getPropertyValue('transform') isn't exactly the same as in the question? – rafaelcastrocouto Oct 04 '16 at 13:03
  • 1
    Yeah, I figured that would provide the gist needed to construct a working version. I have updated the answer to explain how there isn't much difference. – Matt Way Oct 04 '16 at 13:33
  • 1
    Nice... I felt like I had to give you a point since I copied your Math.atan2 angle calculation! – rafaelcastrocouto Oct 04 '16 at 13:49
  • 1
    Looks good! But it doesn't work with rotateX values? Your example is using rotateZ, I guess I should choose other indexes in the last line? https://jsfiddle.net/apg5e2kv/2/ – Alvaro Oct 04 '16 at 14:24
2

The most simple solution I could come up with ...

var el = $('.el');
var matrix = el.css('transform');
var values = matrix.split('(')[1].match(/-?[\d\.]+/g);
var rad = Math.atan2(values[6], values[5]);
if ( rad < 0 ) rad += (2 * Math.PI);
var angle = rad * (180/Math.PI);
el.text(Math.round(angle));
.el {
  width: 50px; height: 50px;
  background: tomato;
  transform: rotate3d(1, 0, 0, 60deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="el"></div>

If you want to use libraries, you can use one of this:

http://github.com/Luxiyalu/jquery-transformer

http://paperjs.org/reference/matrix/

rafaelcastrocouto
  • 11,781
  • 3
  • 38
  • 63
  • Looking good, but fails with -180 deg and returns -129 instead ? https://jsfiddle.net/apg5e2kv/4/ – Alvaro Oct 04 '16 at 15:20
  • Also, any value over 180 won't get retrieved as such, for example `-350` will return `10`. And I'm interested in the absolute value not in the relative one. – Alvaro Oct 04 '16 at 15:26
  • I'm gonna write a full support code for this and update the question. Just gimme a couple hours plz ;D – rafaelcastrocouto Oct 04 '16 at 18:06
  • Just saying, the idea was good, pity it doesn't work to solve the issue proposed in the question. – Alvaro Oct 04 '16 at 20:02
  • All the info we need is at https://drafts.csswg.org/css-transforms/#decomposing-a-3d-matrix – rafaelcastrocouto Oct 04 '16 at 20:31
  • And it's explained in details at https://css-tricks.com/get-value-of-css-rotation-through-javascript/ – rafaelcastrocouto Oct 04 '16 at 20:36
  • The link from css tricks has the same problem as your suggested solution. It provides a relative angle. Regarding the csswg drafts, I could even use that in the question, but wouldn't consider that an answer :) – Alvaro Oct 04 '16 at 20:46
  • It's solved... I updated the answer to keep the code simple ... use this pen as reference of an elaborate solution http://codepen.io/jjeaton/pen/bzolH – rafaelcastrocouto Oct 04 '16 at 20:50
  • Your answer was not updated ? Still having exactly the same issue: https://jsfiddle.net/apg5e2kv/5/ And the codepen you added, none of those 2 functions return the absolute value as expected. See https://jsfiddle.net/apg5e2kv/7/ – Alvaro Oct 04 '16 at 22:57
  • I'm still on this ... but with no success. I managed to return the translation, scale, skew, perspective and quaternion but no luck with the rotation over 3d matrix. Gonna research more tomorrow. Sorry @Alvaro. – rafaelcastrocouto Oct 04 '16 at 23:19
  • 1
    do not think more. There's no mathematical solution to it. I'll provide my own answer explaining it. – Alvaro Oct 05 '16 at 09:45
2

I should have payed a bit more attention to it. After a while I realized this can not be solved mathematically. Not if I want to get the exact absolute degrees and not the relative ones.

The matrix we get with a transformation of 370 degrees is exactly the same one we get with a transformation of 10 degrees. Therefore it is impossible to get two different resulting values for alpha with the exact same input.

with transform: rotate3d(1, 0, 0, 10deg); we get:

matrix3d(1, 0, 0, 0, 0, 0.984808, 0.173648, 0, 0, -0.173648, 0.984808, 0, 0, 0, 0, 1)

And with transform: rotate3d(1, 0, 0, 370deg); the exact same one:

matrix3d(1, 0, 0, 0, 0, 0.984808, 0.173648, 0, 0, -0.173648, 0.984808, 0, 0, 0, 0, 1)

Reproduction online

Alvaro
  • 40,778
  • 30
  • 164
  • 336
  • That's really interesting, but can we have a good relative solution? I'm still trying ... (by good I mean without the 180º to 129º error and with a reasonable performance) – rafaelcastrocouto Oct 05 '16 at 10:57