【译】CSS动画 vs JS动画

原文地址javascript

目前有两个主流的方法在web上建立动画:使用CSS或JS。到底选择哪一种方法来实现动画,彻底取决于你的项目以及你想要达到的效果。css

tips:java

  • 对于简单的只出现一次的过渡效果,能够采用CSS动画,好比切换UI元素的状态
  • 在须要高级的效果,好比弹跳、中止、暂停、倒回或者减速这种效果,就须要用JS来实现动画
  • 若是用JS实现动画,能够用TweenMax,或者若是须要轻量级的解决方案,就用TweenLite

不少基础的动画均可以经过CSS或JS来实现,但二者的效果和时间会有差异。两种方式各有千秋:git

  • 对UI元素小而独立的状态添加动画,可使用CSS。CSS的transitionanimation是一个好办法,好比把导航栏从侧边移过来,或者展现一个提示框tooltip。这种状况下最好用CSS而不是JS
  • 在须要对动画进行精确控制的时候须要用JS实现。JS能够动态跟踪触发动画的位置,像一些中止、暂停、减速或者反转的效果都须要JS实现。

若是你已经用了相似jQuery的包含动画函数的JS框架,你会发现用它来控制动画比CSS方便的多。github

CSS动画

毫无疑问CSS动画是最简单的一种让屏幕上的元素动起来的方式。web

下面的CSS代码会将一个元素在X轴和Y轴上移动100px。完成这个功能须要CSS trasition,并设置为500ms。当move这个class被添加时,transform的值会发生改变,过渡开始浏览器

.box {
  -webkit-transform: translate(0, 0);
  -webkit-transition: -webkit-transform 500ms;

  transform: translate(0, 0);
  transition: transform 500ms;
}

.box.move {
  -webkit-transform: translate(100px, 100px);
  transform: translate(100px, 100px);
}

你若是像上面的代码片断同样添加了CSS类来控制动画,那么接下来就须要用JS来控制切换动画的开始和结束app

box.classList.add('move');

采用这种方式会对你的app有很好的平衡。你只须要用JS来控制状态,而后对目标元素设置恰当的class,让浏览器来控制动画。接下来你能够对目标元素监听transitionend事件,不过这种状况只适用于IE10+。这个事件在CSS完成过渡之后触发。框架

var box = document.querySelector('.box');
box.addEventListener('transitionend', onTransitionEnd, false);

function onTransitionEnd() {
  // Handle the transition finishing.
}

除了用CSS transitions,你也可使用CSS animations,它能让你对动画的帧、时长及重复次数有更多的控制。函数

Note

若是你是动画新手,对于手绘动画而言关键帧(keyframes)是很重要的概念。动画会生成一些特殊的帧来实现一个动做,这种帧叫作keyframes,这种帧可以捕捉某些动做的最极端的部分。CSS动画也有类似的过程,经过设置CSS的相关属性在目标点的时候什么值就能够了。

举一个例子,让盒子的动画跟上例同样,只是不须要任何像click的事件触发,而且无限重复。你能够同时改变多个属性:

/**
 * This is a simplified version without
 * vendor prefixes. With them included
 * (which you will need) things get far
 * more verbose!
 */
.box {
  /* Choose the animation */
  animation-name: movingBox;

  /* The animation’s duration */
  animation-duration: 1300ms;

  /* The number of times we want
      the animation to run */
  animation-iteration-count: infinite;

  /* Causes the animation to reverse
      on every odd iteration */
  animation-direction: alternate;
}

@keyframes movingBox {
  0% {
    transform: translate(0, 0);
    opacity: 0.3;
  }

  25% {
    opacity: 0.9;
  }

  50% {
    transform: translate(100px, 100px);
    opacity: 0.2;
  }

  100% {
    transform: translate(30px, 30px);
    opacity: 0.8;
  }
}

经过CSS动画,你能够为目标元素单独定义动画,并使用animation-name属性来选择须要的动画。CSS动画目前还须要写前缀,在Chrome,Safari,Opera,Safari Mobile以及Android Browser中均须要添加-webkit-前缀。IE和Firefox均不须要写前缀。有不少工具会帮你在须要添加前缀的属性上添加前缀,这样在源代码中就能够不须要一个个添加前缀了。

JS动画

跟CSS动画相比,JS动画更复杂一些,但会给开发者更多的动画能力。推荐的作法是使用requestAnimationFrame,在动画的每一个帧上来肯定元素的每一个属性值。(关于requestAnimationFrame,可参考HTML5探秘:用requestAnimationFrame优化Web动画

Note

你应该见到过不少用setInterval或者setTimeout来实现动画的代码。然而这是一个很差的方法,动画会不能跟屏幕同步刷新,并且很容易剧烈变化或者跳出。你须要避免这样的代码,尽可能使用requestAnimationFrame,它可以正确的同步。

下面的例子是你须要写的JS代码,实现上面用CSS实现的效果:

function Box () {

  var animationStartTime = 0;
  var animationDuration = 500;
  var target = document.querySelector('.box');

  this.startAnimation = function() {
    animationStartTime = Date.now();
    requestAnimationFrame(update);
  };

  function update() {
    var currentTime = Date.now();
    var positionInAnimation = (currentTime - animationStartTime) / animationDuration;

    var xPosition = positionInAnimation * 100;
    var yPosition = positionInAnimation * 100;

    target.style.transform = 'translate(' + xPosition + 'px, ' + yPosition + 'px)';

    if (positionInAnimation <= 1)
      requestAnimationFrame(update);
  }
}

var box = new Box();
box.startAnimation();

上面的代码看起来很复杂,你能够尝试将其扩展到多种状况。若是你正在使用jQuery,能够用.animate()函数。若是不是,你能够参考强大的Greensock’s TweenMax,还有一个轻量级的TweenLite。

相关文章
相关标签/搜索