Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS rotation cross browser with jquery.animate()

I'm working on creating a cross-browser compatible rotation (ie9+) and I have the following code in a jsfiddle

$(document).ready(function () {      DoRotate(30);     AnimateRotate(30); });  function DoRotate(d) {      $("#MyDiv1").css({           '-moz-transform':'rotate('+d+'deg)',           '-webkit-transform':'rotate('+d+'deg)',           '-o-transform':'rotate('+d+'deg)',           '-ms-transform':'rotate('+d+'deg)',           'transform': 'rotate('+d+'deg)'      });   }  function AnimateRotate(d) {          $("#MyDiv2").animate({           '-moz-transform':'rotate('+d+'deg)',           '-webkit-transform':'rotate('+d+'deg)',           '-o-transform':'rotate('+d+'deg)',           '-ms-transform':'rotate('+d+'deg)',           'transform':'rotate('+d+'deg)'      }, 1000);  } 

The CSS and HTML are really simple and just for demo:

.SomeDiv{     width:50px;     height:50px;            margin:50px 50px;     background-color: red;}  <div id="MyDiv1" class="SomeDiv">test</div> <div id="MyDiv2" class="SomeDiv">test</div> 

The rotation works when using .css() but not when using .animate(); why is that and is there a way to fix it?

Thanks.

like image 980
frenchie Avatar asked Mar 03 '13 21:03

frenchie


1 Answers

CSS-Transforms are not possible to animate with jQuery, yet. You can do something like this:

function AnimateRotate(angle) {     // caching the object for performance reasons     var $elem = $('#MyDiv2');      // we use a pseudo object for the animation     // (starts from `0` to `angle`), you can name it as you want     $({deg: 0}).animate({deg: angle}, {         duration: 2000,         step: function(now) {             // in the step-callback (that is fired each step of the animation),             // you can use the `now` paramter which contains the current             // animation-position (`0` up to `angle`)             $elem.css({                 transform: 'rotate(' + now + 'deg)'             });         }     }); } 

You can read more about the step-callback here: http://api.jquery.com/animate/#step

http://jsfiddle.net/UB2XR/23/

And, btw: you don't need to prefix css3 transforms with jQuery 1.7+

Update

You can wrap this in a jQuery-plugin to make your life a bit easier:

$.fn.animateRotate = function(angle, duration, easing, complete) {   return this.each(function() {     var $elem = $(this);      $({deg: 0}).animate({deg: angle}, {       duration: duration,       easing: easing,       step: function(now) {         $elem.css({            transform: 'rotate(' + now + 'deg)'          });       },       complete: complete || $.noop     });   }); };  $('#MyDiv2').animateRotate(90); 

http://jsbin.com/ofagog/2/edit

Update2

I optimized it a bit to make the order of easing, duration and complete insignificant.

$.fn.animateRotate = function(angle, duration, easing, complete) {   var args = $.speed(duration, easing, complete);   var step = args.step;   return this.each(function(i, e) {     args.complete = $.proxy(args.complete, e);     args.step = function(now) {       $.style(e, 'transform', 'rotate(' + now + 'deg)');       if (step) return step.apply(e, arguments);     };      $({deg: 0}).animate({deg: angle}, args);   }); }; 

Update 2.1

Thanks to matteo who noted an issue with the this-context in the complete-callback. If fixed it by binding the callback with jQuery.proxy on each node.

I've added the edition to the code before from Update 2.

Update 2.2

This is a possible modification if you want to do something like toggle the rotation back and forth. I simply added a start parameter to the function and replaced this line:

$({deg: start}).animate({deg: angle}, args); 

If anyone knows how to make this more generic for all use cases, whether or not they want to set a start degree, please make the appropriate edit.


The Usage...is quite simple!

Mainly you've two ways to reach the desired result. But at the first, let's take a look on the arguments:

jQuery.fn.animateRotate(angle, duration, easing, complete)

Except of "angle" are all of them optional and fallback to the default jQuery.fn.animate-properties:

duration: 400 easing: "swing" complete: function () {} 

1st

This way is the short one, but looks a bit unclear the more arguments we pass in.

$(node).animateRotate(90); $(node).animateRotate(90, function () {}); $(node).animateRotate(90, 1337, 'linear', function () {}); 

2nd

I prefer to use objects if there are more than three arguments, so this syntax is my favorit:

$(node).animateRotate(90, {   duration: 1337,   easing: 'linear',   complete: function () {},   step: function () {} }); 
like image 122
22 revs, 4 users 88% Avatar answered Oct 27 '22 16:10

22 revs, 4 users 88%