1

I'm trying to rotate any .test div clockwise by 180˚ each time it is clicked.

What I have done is essentially:

  • If no rotation has occurred, rotate to 180˚.
  • If it's been rotated to 180˚, rotate to 360˚.
  • If it's been rotated to 360˚, remove transform and transition properties and rotate to 180˚.

$(".test").click(function(){
    var angle;
    var matrix = $(this).css("-webkit-transform")
    if (matrix == "none") { //div hasn't been rotated yet
        angle = 0;
    }
    else {
        var values = matrix.split('(')[1].split(')')[0].split(',');
        var a = values[0]; //should be -1 if div is upside down, 1 if it is normal.
        if(a == 1) { 
            $(this).removeAttr('style');
            angle = 0;
        }
        else {
            angle = 180;
        }   
    }
    $(this).css({
        "-webkit-transform": "rotate("+(angle+180)+"deg)",
        "-moz-transform": "rotate("+(angle+180)+"deg)",
        "transform": "rotate("+(angle+180)+"deg)",
        "-webkit-transition": "-webkit-transform 0.3s ease-in", 
    });
});

This works fine for first two clicks, but on the third click, the div rotates counterclockwise, as if it's rotating from 360˚ to 180˚, despite the fact that I've already removed the style attribute.

Here's a working fiddle: https://jsfiddle.net/wwny5q5d/3/

Now, the thing that's got me really curious is that if I add an alert or debugger before calling .css(), the third rotation goes as I want it to, clockwise.

alert("Now it will always rotate clockwise")
$(this).css({
    "-webkit-transform": "rotate("+(angle+180)+"deg)",
    "-moz-transform": "rotate("+(angle+180)+"deg)",
    "transform": "rotate("+(angle+180)+"deg)",
    "-webkit-transition": "-webkit-transform 0.3s ease-in", 
});

So my questions are: Why doesn't my div rotate clockwise on the third click, AND why does the inclusion of the alert make it work?

digglemister
  • 1,477
  • 3
  • 16
  • 31
  • @Gothdo Because I can't distinguish between it being at 0˚ or 360˚ degrees unless I use some sort of counter, which I don't want since there are a bunch of `.test` divs. So how would I know if I want to rotate to 180˚ or 540˚? – digglemister Apr 13 '16 at 20:36
  • @Gothdo I'm not sure I follow. Are you saying just add 180 to its current rotation? Because the problem is that I don't know how much it's been rotated already, I only know the values in the rotation matrix, which are equivalent mod360. – digglemister Apr 13 '16 at 21:47
  • Yes, see http://stackoverflow.com/questions/13592384/how-to-retrieve-the-angle-in-css3-rotate – Michał Perłakowski Apr 13 '16 at 21:49
  • @Gothdo But again, the issue is that after two clicks I'm at 360˚, but then getting this angle using the method in the question you posted gives me 0˚. So if I simply add 180˚ to this, it moves me counterclockwise from 360 to 180. – digglemister Apr 13 '16 at 21:54
  • @Gothdo The computed value of the amount rotated, using the method in the question you posted, is always [0,360) while the css property -webkit-transform could have any value. – digglemister Apr 13 '16 at 21:56

2 Answers2

2

Use

this.style.cssText.match(/\((\d+)deg\)/)[1])

to get the original, non-computed value.

See JS Fiddle demo.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • Awesome, that'll do it, I really appreciate the help. Any ideas why in my original code the rotation is being applied before the style attribute is removed? – digglemister Apr 13 '16 at 22:05
  • @snookieordie Because you're adding new styles *immediately* after removing `style` element. If you delayed setting new styles with `setTimeout(function(){}, 0)`, browser would repaint the element, and apply new styles to the repainted element. – Michał Perłakowski Apr 13 '16 at 22:14
  • @snookieordie For better understanding, I'll give you two examples one JS Fiddle. In [the first](https://jsfiddle.net/03mpau55/), if you click the `div` second time, it won't enlarge, because new styles are applied immediately after the old ones are removed, so browser interprets it as "nothing changed". In [the second](https://jsfiddle.net/schnkjhp/), however, after removing the old styles browser repaints the `div`, and after that applies new styles. – Michał Perłakowski Apr 13 '16 at 22:21
0

In your fiddle, the rotation is being applied to the div when its at 360 before the style is removed from the div. So it's setting the angle to 0 and then rotating back to 180 based off angle = 0. The alert dialog adds a delay before the CSS is set, which allows for the removal of the styling, then the angle is set to 0, then the CSS is appplied. I believe what @Gothdo above is saying is to continually add 180 to the div rotation instead of resetting the angle back to zero. You can see that done Here

Community
  • 1
  • 1
Hoopson2
  • 126
  • 6
  • Any ideas why the rotation is being applied before the style is being removed? It's not clear to me from my code why this would happen. And the issue with the example you show is that it relies on a counter, it adds 5 to `rotation` each click, or something similar. My issue is that I don't want to have 100 separate counters for 100 separate divs, if it can be avoided. – digglemister Apr 13 '16 at 22:03