Smooth animation of element type swing via CSS transform

9
The concept that is trying to reach is the continuous movement on the axis of the X between a value and its representation in negative:

So far, this concept has a failure, the animation is performed from 0 degrees to the value given, but then when going back to the same negative value, there is a 0 degree jump and only then it animates to or value provided. The same thing happens when you return to the positive value:

See example in JSFiddle

$.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);
  });
};

// animate snowman
var d = 5;

function jingle() {
  $("#snowman").animateRotate(d, {
    duration: 1337,
    easing: 'linear',
    complete: function () {
      jingle(d = -d);
    }
  });
}

jingle();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><imgid="snowman" alt="snowman" src="http://i.stack.imgur.com/AmNNj.png">

Theobjecttoanimate

Theimagebelowistheobjectyouwanttoanimateasyoucanparseinthedemonstrations.

Question

How can I smooth the effect so as to reach the desired animation curve?

    
asked by anonymous 16.12.2014 / 12:47

3 answers

6

One suggestion is to trust this animation in CSS, via transition of transform: rotate() .

I think jQuery can be simplified to:

var ang = -5;
var el = document.querySelector('img');

setInterval(function () {
    ang = -ang;
    el.style[prefix + 'transform'] = 'rotate(' + ang + 'deg)';
}, 1000);

and CSS

img {
    -moz-transition: all 1s ease-in-out;
    -webkit-transition: all 1s ease-in-out;
    -o-transition: all 1s ease-in-out;
    transition: all 1s ease-in-out;
}

and adding a fix for browsers that need suffix can be used

var prefix = (function () {
    var styles = window.getComputedStyle(document.documentElement, ''),
        pre = (Array.prototype.slice.call(styles)
            .join('')
            .match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o']))[1];
    if (pre == 'moz') return '';
    return '-' + pre + '-';
})();

(adapted / imported from David Walsh's blog)

In this case the animation would be: link

    
16.12.2014 / 12:55
7

Using @keyframes together with the property animation to have control over the animation.

Keyframes in MDN

Animations in MDN

For this case, only with CSS, a possible solution would be:

@-webkit-keyframes snowman {
    from {-webkit-transform: rotate(4deg)}
    to   {-webkit-transform: rotate(-4deg)}
}

@keyframes snowman {
    from {transform: rotate(4deg)}
    to   {transform: rotate(-4deg)}
}

#snowman {
    -webkit-animation: snowman 2s alternate infinite ease-in-out;
            animation: snowman 2s alternate infinite ease-in-out;
}
<img id="snowman" alt="snowman" src="http://i.stack.imgur.com/AmNNj.png">
    
16.12.2014 / 13:21
4

Forget about the code part, let's think about the following:

  • When a rounded object resting on the ground rotates, it also moves to the side corresponding to the turn.

  • In addition, the shadow does not rotate together, but rather projects itself according to the shape of the object. In this case, the shadow is a "generic spot" because it is a drawing only, but it is expected to move according to the object.


From this, I divided the doll in question into two images: The own, and the shadow.

As already replied by @Renan (which also received my upvote ), keyframes are an interesting path for this type of animation because they will usually be managed by a separate subsystem of the browser , probably in a separate thread from JS, ensuring a more fluid animation, at the same time overloading less the main application (but note "note 2" in the footer of the question , to see the points against).


Putting all this together, the result (the vendor-prefix disrupts the elegance a little):

@-webkit-keyframes snowman { from { -webkit-transform: translateX(-20px) rotate(-10deg) }
                             to   { -webkit-transform: translateX( 20px) rotate( 10deg) } }
@-webkit-keyframes shadow  { from { -webkit-transform: translateX(-10px) }
                             to   { -webkit-transform: translateX( 10px) } }
@keyframes snowman         { from { transform: translateX(-20px) rotate(-10deg) }
                             to   { transform: translateX( 20px) rotate(  0deg) } }
@keyframes shadow          { from { transform: translateX(-10px) }
                             to   { transform: translateX( 10px) } }
#snowman { -webkit-animation: snowman 2s alternate infinite ease-in-out;
                   animation: snowman 2s alternate infinite ease-in-out; z-index:10; }
#shadow  { -webkit-animation: shadow  2s alternate infinite ease-in-out;
                   animation: shadow  2s alternate infinite ease-in-out; z-index: 0; }
#boneco { min-height: 350px } #boneco img { position: absolute; }
<p>Aumente a janela ou use a barra de rolagem para ver o efeito.</p>
<div id="boneco">
  <img id="snowman" src="http://i.stack.imgur.com/GRMcV.png"><imgid="shadow"  src="http://i.stack.imgur.com/ZDz9I.png"></div>

Note1:@Sergio'sresponseisalsointerestingformorecomplexsituationswherethekeyframemightbeinsufficient,aswellasaveryinterestingcompatibilitylayer.

Note2:saidthis, here has an article (en) which shows that keyframes also has its problems, and one of them is synchronization. It pays to read.

    
17.12.2014 / 01:13