1. 程式人生 > >中斷與停止CSS transition

中斷與停止CSS transition

可能本來就是這樣,處於階段的CSS3就不該大規模應用,瀏覽器商只是用它炫耀CSS能做行為層的事兒。現在人們比對待IE的CSS濾鏡寬容多了,因此這事情還是逐一被其他瀏覽器所接受。在CSS3提供的兩上實現動畫的方案中,transition與animation,animation在DOM中沒有對應的API,而transition則在我們動畫暫停時遇上滑鐵盧了——在webkit與opera中,我們是無法用removeProperty去掉transition的效果,一經定義就永遠持續下去。在firefox中,我們還可以用覆寫的方式去掉它們。

在開始演示之前,我給出取得CSS3 WebKitTransitionEvent事件名的方法:

var getTransitionEndEventName = function(){ var obj = { 'WebKitTransitionEvent': 'webkitTransitionEnd', 'TransitionEvent': 'transitionend', 'OTransitionEvent': 'oTransitionEnd' }, ret ,e; for (var name in obj) { try { document.createEvent(name); ret =  obj[name]; console.log(ret)
} catch (ex) { } } getTransitionEndEventName = function(){ return ret } return ret; } getTransitionEndEventName();

由於無法在webkit與opera上清除transition,這事件就可能無數次觸發,這可不是我們願意看到的。因此我們每次在中斷或停止動畫必須就元素解除繫結。

好了,下面進入正題。

方案一:使用一個新節點做替身。我們可以用cloneNode(true)弄一個一模一樣的節點插入到原節點的前面,然後隱藏原來,將transition設定在新節點上,當動畫中斷或停止時,把當前的樣式覆蓋到原節點上,讓它顯示出來,再移除新節點!

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>dom Framework</title>
    <script>
      var dom = function(s){
        return document.getElementById(s)
      }


      dom.cssName = function (name){
        var prefixes = ['', '-ms-','-moz-', '-webkit-', '-khtml-', '-o-'],
        rcap = /-([a-z])/g,capfn = function($0,$1){
          return $1.toUpperCase();
        };
        dom.cssName = function(name, target, test){
          target = target || document.documentElement.style;
          for (var i=0, l=prefixes.length; i < l; i++) {
            test = (prefixes[i] + name).replace(rcap,capfn);
            if(test in target){
              return test;
            }
          }
          return null;
        }
        return dom.cssName(name);
      }
      window.onload = function(){
        var el = dom("test"),
        css3transition = dom.cssName("transition");
        var  animate = el.cloneNode(true);
        animate.innerHTML = "新節點"
        el.parentNode.insertBefore(animate,el);
        el.style.display = "none";
        animate.style[css3transition] = "all 1.5s ease-in"
      
        setTimeout(function(){
          animate.style.width = "400px";
        },0)
        setTimeout(function(){
          animate.style.width = "100px";
          animate.addEventListener("transitionend",function(){
            el.style.width = "100px"
            el.style.display = ""
            el.parentNode.removeChild(animate)
          },true)
        
        },1000)  ;
        //  setTimeout(function(){
        //   el.style.width = "300px";
        // },5000)  
      }
    </script>
    <style>
      #test{
        background: red;
        width:10px;
        height:30px;
      }
      #parent{
        width:410px;
        height: 32px;
        border: 1px solid blue;
      }
    </style>
  </head>
  <body>
    <h3>CSS3 動畫 by 司徒正美</h3>
    <div id="parent">
      <div id="test">
        TEXT
      </div>
    </div>


    <button id="start" type="button">開始測試</button>
  </body>
</html>
    

但人們想在動畫中進行對它進行操作呢?因為節點已不是原來的節點,因此維護成本非常高!

方案2:無視transition的永久效果。因為在中斷或停止時,我們把當前樣式取出來再覆蓋上去,也可以中止動畫。

<!DOCTYPE html>
<html>


  <head>
    <meta charset="utf-8">
    <title>dom Framework</title>
    <script>
      var dom = function(s){
        return document.getElementById(s)
      }


      dom.cssName = function (name){
        var prefixes = ['', '-ms-','-moz-', '-webkit-', '-khtml-', '-o-'],
        rcap = /-([a-z])/g,capfn = function($0,$1){
          return $1.toUpperCase();
        };
        dom.cssName = function(name, target, test){
          target = target || document.documentElement.style;
          for (var i=0, l=prefixes.length; i < l; i++) {
            test = (prefixes[i] + name).replace(rcap,capfn);
            if(test in target){
              return test;
            }
          }
          return null;
        }
        return dom.cssName(name);
      }
      window.onload = function(){
        var el = dom("test"),start,
        css3transition = dom.cssName("transition");
     
        el.style[css3transition] = "all 5000ms ease-in"
        
        dom("pause").onclick = function(){
          var computedStyle = document.defaultView.getComputedStyle( el, null );
          el.style.width = computedStyle.getPropertyValue( "width" );
          var elapsed = new Date - start;
          var old = el.style[css3transition]
          el.style[css3transition] = old.replace(/\d+ms/g,function(a){
            return (parseFloat(a) - elapsed) +"ms"
          })
         //  el.style[css3transition] = "all 5000ms ease-in"
        }
        dom("resume").onclick = function(){
          el.style.width = "400px";
        }
        setTimeout(function(){
          start = new Date;
          el.style.width = "400px";
        },0);
  
        
      }
    </script>
    <style>
      #test{
        background: red;
        width:10px;
        height:30px;
      }
      #parent{
        width:400px;
        height: 31px;
        border: 1px solid blue;
      }
    </style>
  </head>
  <body>
    <h3>CSS3 動畫 by 司徒正美</h3>
    <div id="parent">
      <div id="test">
        TEXT
      </div>
    </div>
    <button id="pause" type="button">中斷</button>
    <button id="resume" type="button">繼續</button>
  </body>
</html>

但無視終歸是逃避問題,不清除transition,以後每次對元素的CSS操作都會動畫化(除了在FF中),因此也不可行。

綜上所述,CSS3對行為層的干涉至今還是不成熟的。作為一個成熟的框架不應該把它作為構建動畫的手段。

原文地址:http://www.cnblogs.com/rubylouvre/archive/2011/09/11/2172539.html