【譯】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。

相關文章
相關標籤/搜索