6

In this example; i am trying to create a jQuery animation with css3 rotate property. I can manage this animation with css3 transition and jQuery css() but i want to do this with jQuery animate() for rotating deg value according to my jQuery variatons.

Is it possible use animate with css3 property value with jQuery 1.8.0?

Here is jsFiddle to inspect.

jQuery:

var rotateVal = 90;

//this method isn't working
$('.red').animate({
    'transform':'rotate('+rotateVal+'deg)'
},500);


//this way works but i don't want to do this with transitions
$('.black').css({
    'transform':'rotate('+rotateVal+'deg)',
    'transition':'1s'
});​

html:

<span class="black"></span>
<span class="red"></span>

Edit: Vendor prefixes removed, like -webkit-. Thanks to Kevin B.

Barlas Apaydin
  • 7,233
  • 11
  • 55
  • 86
  • Be sure to use -ms-transform as well (I added a fiddle in the comments of the answer), otherwise it won't work in IE9. – Ben Lesh Aug 28 '12 at 13:29
  • @blesh It is working just fine on ie9 without `-ms-trasnform`. Kevin B. mentioned this issue on his answer; jQuery 1.8 fixes that: "*note that in 1.8.0 i don't think you need to specify all the vendor prefixes.*" – Barlas Apaydin Aug 28 '12 at 13:52
  • Hmmm, the reason I added it is because I tried it in IE9 and it didn't work. It is, however, working now. – Ben Lesh Aug 28 '12 at 13:55
  • I swear. haha. So weird. I mean, i tried it, and it didn't work, and I thought, "Huh? well I wonder what needs done to make it work?" Maybe there was a glitch in jsfiddle and it loaded the wrong JQuery? – Ben Lesh Aug 28 '12 at 13:56

3 Answers3

6

It is possible, but it isn't easy.

var red = $(".red"),
    rotateVal = 90;
$("<div />").animate({
    height: rotateVal
},{
    duration: 500,
    step: function(now){
        red.css('transform','rotate('+now+'deg)');
    }
});

This basically creates a fake animation of a detached div, then on each step, updates the rotation of the target div.

Edit: Oops! wrong argument order. Here's a demo. http://jsfiddle.net/qZRdZ/

note that in 1.8.0 i don't think you need to specify all the vendor prefixes.

Using this method, you can animate almost anything as long as you keep in mind that things like += and -= won't work properly unless coded for.

Update: Here's a combination of my solution and cuzzea's solution abstracted behind a function. http://jsfiddle.net/qZRdZ/206/

$.fn.rotate = function(start, end, duration) {
    console.log(this);
    var _this = this;
    var fakeDiv = $("<div />");
    _this.promise().done(function(){
        _this.animate({"a":end},{duration:duration});
        fakeDiv.css("height", start).animate({
            height: end
        }, {
            duration: duration,
            step: function(now) {
                _this.css("transform", "rotate(" + now + "deg)");
            },
            complete: function() {
                fakeDiv.remove();
            }
        });
    });

    return _this;
};

var red = $('.red');
red.click(function() {
    if ( !$(this).is(':animated') ) {

        red.rotate(45,135,500);
        setTimeout(function(){
            red.rotate(135,190,500);
        },750);
        setTimeout(function(){
            red.rotate(190,45,500);
        },1500);
    }
});

});

Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Why are you using `height` property in animate for rotateVal? And what is `step:` method ? Is that [animate's](http://api.jquery.com/animate/) easing or complete method? – Barlas Apaydin Aug 21 '12 at 21:13
  • It is a separate method that gets called on each step of the animation. I used height, you can use any css property such as height, width, padding-left, etc. Any numerical css property that can be animated. It's purpose is simply to fire the step method with an accurate `now` value – Kevin B Aug 21 '12 at 21:15
  • your answer and your jsFiddle has a different point, you define css porperties to `$("
    ")` selector, why these css properties there? and why didn't you just use `$('.red')` selector over there?
    – Barlas Apaydin Aug 22 '12 at 19:03
  • Thanks for the answer again mate, +1 from me. Your way is working but it is really complicated. I started to questioning my jQuery knowledge again. – Barlas Apaydin Aug 22 '12 at 19:07
  • 1
    the .css was left over from testing, it isn't needed. http://jsfiddle.net/qZRdZ/13/ – Kevin B Aug 22 '12 at 19:12
  • 2
    I used `$("
    ")` because i wanted to do the height animation on a fake element so that it wouldn't impact the page.
    – Kevin B Aug 22 '12 at 19:13
  • Thanks again for good answers, i want to give +500 for this (: [**Your way is working perfect**](http://jsfiddle.net/qZRdZ/40/) but still looking for way with **less code**. – Barlas Apaydin Aug 25 '12 at 20:34
  • @barlasapaydin As far as less code, you can always make it *look* like less code by placing it in a re-usable function. – Kevin B Aug 25 '12 at 21:31
  • You gave me no chanse to not accept your answer (: thank you very much and i'll give more points for this answer. – Barlas Apaydin Aug 25 '12 at 21:48
  • basically in IE9 you need to use `-ms-trasnform`, as `transform` doesn't work. – Ben Lesh Aug 28 '12 at 13:29
  • @blesh No need to use vendor prefixes mate, jQuery 1.8 fixes that. I've tested that in ie9 and also this issue mentioned in this answer too. – Barlas Apaydin Aug 28 '12 at 13:49
  • I used the exact jsfiddle from this answer, and it didn't work in IE9 until I made the changes. ... but now it is. Maybe a glitch with jsfiddle then? – Ben Lesh Aug 28 '12 at 13:57
  • @Blesh yes, if you look back in the revisions, my original answer had the vendor prefixes, then i added the note for 1.8.0, then eventually removed them to simplify the answer. – Kevin B Aug 28 '12 at 14:18
  • *shrug*... well that was wierd. I'm going to blame jsfiddle for now. ;) – Ben Lesh Aug 28 '12 at 14:25
  • @KevinB I discovered a bug on your latest answer and cound't solve it: `red.rotate(0,90,500).delay(250).rotate(90,-360,1500);` no matter what you define on `start` parameter, it always start from `0`. You can inspect problem carefully on this jsFiddle: **http://jsfiddle.net/qZRdZ/109/** – Barlas Apaydin Aug 30 '12 at 12:20
  • @KevinB is it possible to fix start value? Thanks – Barlas Apaydin Aug 30 '12 at 13:47
  • Now it properly works with `.delay` and `:animated` http://jsfiddle.net/qZRdZ/112/ updating answer – Kevin B Aug 30 '12 at 14:49
  • lol answer became a plugin (: thanks again for fast return, i'll play with fiddle when i sit on a computer. – Barlas Apaydin Aug 30 '12 at 15:09
  • @barlasapaydin One definitely already exists, but I don't think it's as simple as this one. – Kevin B Aug 30 '12 at 15:11
  • hello, it's me again (: i discovered that if you add 3rd rotate animation, it won't work. http://jsfiddle.net/qZRdZ/204/ – Barlas Apaydin Jan 25 '13 at 14:50
  • @barlas Sorry for the delay, you have to use setTimeout instead of delay to get consistent results since we are using a fake element to do the animation. http://jsfiddle.net/qZRdZ/206/ – Kevin B Jan 28 '13 at 18:55
3

Kevin is corect, almost. :)

Here is working jsFiddle.

You don't have to use another element and height, you can do something like:

var red = $('.red'),
max_rot = 45,
start_from = 90;

red.css({a:0}).animate(
    {'a':1},
    { step: function(value,tweenEvent)
       {
         rotateVal = start_from + max_rot * value;
         red.css({
           'transform':'rotate('+rotateVal+'deg)',
         });
       }
     },
1000);​

The ideea is simple. First we create a bogus css property 'a' and set it to 0, and then we animate it to 1, so the step function will give you a value of 0 to 1 that you can use to set the custom transform.

Barlas Apaydin
  • 7,233
  • 11
  • 55
  • 86
cuzzea
  • 1,515
  • 11
  • 22
  • Thanks for detailed answer mate, **+1** from me. I've got lost of questions on [**this jsFiddle**](http://jsfiddle.net/qZRdZ/33/) and most important question is: Why [**@KevinB 's answer**](http://jsfiddle.net/qZRdZ/40/) returns true `rotateVal = 90` value and [**your answer's value is returns different,**](http://jsfiddle.net/qZRdZ/42/) which should be `90`. I think there is a problem with rotateVal formula. – Barlas Apaydin Aug 25 '12 at 20:24
  • @cuzzea if you reorganize it like this I think it makes more sense: http://jsfiddle.net/qZRdZ/44/ – Kevin B Aug 25 '12 at 21:28
  • 1
    @barlasapaydin you just have to adjust the variables: http://jsfiddle.net/qZRdZ/45/ – Kevin B Aug 25 '12 at 21:30
  • @Kevin B you are right, but it seems you got it better in your answer :) – cuzzea Aug 26 '12 at 07:14
  • 1
    @cuzzea It seems that using 'a' on the target element won't allow you to use a start position that isn't 0. http://jsfiddle.net/qZRdZ/113/ just an FYI. I had to go back to using fakeDiv. – Kevin B Aug 30 '12 at 14:55
0

An alternative method would be to use jQuery to change the dom to something that css would respond to.

We can set our css to look like this:

.object {
    -webkit-transition:all .4s;
    -moz-transform:all .4s;
    -o-transform:all .4s;
    -ms-transform:all .4s;
    transform:all .4s;
}
.object[data-rotate="false"] {
    -webkit-transform:rotate(0deg);
    -moz-transform:rotate(0deg);
    -o-transform:rotate(0deg);
    -ms-transform:rotate(0deg);
    transform:rotate(0deg);
}
.object[data-rotate="true"] {
    -webkit-transform:rotate(90deg);
    -moz-transform:rotate(90deg);
    -o-transform:rotate(90deg);
    -ms-transform:rotate(90deg);
    transform:rotate(90deg);
}

Our jQuery would look like this:

$('#trigger').live('click',function(){
    if($('.object').attr('data-rotate') = true) {
        $('.object').attr('data-rotate',false);
    }
    else {
        $('.object').attr('data-rotate', true);
    }
});

Obviously, the browser has to support the ability to transform whatever animation you want to run, so its its hit or miss depending on the type of animation, but its nicer to work with if you have a ton of stuff going on or you have some children you want to animate concurrently.

Example fiddle: http://jsfiddle.net/ddhboy/9DHDy/1/

ddhboy
  • 116
  • 4