2010-06-04 105 views
19

我有一個非常簡單的演示工作,它使用Webkit轉換和轉換以實現'面板'(div)之間的平滑水平滾動。如何修復使用Webkit轉換和轉換時的閃爍

我想走這條路線,而不是一個Javascript驅動系統的原因是,它的iPad和Javascript性能相當差,但CSS轉換和過渡是平滑的絲綢。可悲的是,我的演示在iPad上出現了很多閃爍現象。

你可以看到the demo here

你需要Safari或和iPad,看看它在行動。我從未在轉換和轉換的任何演示中看到過這種情況,所以我希望這是可以解決的。

無論如何,這裏的代碼,權力的東西....

HTML看起來像這樣。

<html> 
    <head> 
     <title>Swipe Demo</title> 
     <link href="test.css" rel="stylesheet" /> 
     <link href="styles.css" rel="stylesheet" /> 
     <script type="text/javascript" src="jquery.js"></script> 
     <script type="text/javascript" src="functions.js"></script> 
     <script type="text/javascript" src="swiping.js"></script> 
    </head> 
    <body> 


    <div id="wrapper"> 
     <div class='panel one'> 
      <h1>This is panel 1</h1> 
     </div> 

     <div class='panel two'> 
      <h1>This is panel 2</h1> 
     </div> 

     <div class='panel three'> 
      <h1>This is panel 3</h1> 
     </div> 

     <div class='panel four'> 
      <h1>This is panel 4</h1> 
     </div> 
    </div> 

    </body> 
</html> 

的CSS看起來像這樣

body, 
    html 
     { 
      padding: 0; 
      margin: 0; 
      background: #000; 
     } 

    #wrapper 
     { 
      width: 10000px; 
      -webkit-transform: translateX(0px); 
     } 

    .panel 
     { 
      width: 1024px; 
      height: 300px; 
      background: #fff; 
      display: block; 
      float: left; 
      position: relative; 
     } 

和JavaScript看起來像這樣

// Mouse/iPad Touch 
var touchSupport = (typeof Touch == "object"), 
touchstart = touchSupport ? 'touchstart' : 'mousedown', 
touchmove = touchSupport ? 'touchmove' : 'mousemove', 
touchend  = touchSupport ? 'touchend' : 'mouseup'; 

$(document).ready(function(){ 

    // set top and left to zero 
    $("#wrapper").css("top", 0); 
    $("#wrapper").css("left", 0); 

    // get total number of panels 
    var panelTotal; 
    $(".panel").each(function(){ panelTotal += 1 }); 

    // Touch Start 
    // ------------------------------------------------------------------------------------------ 

    var touchStartX; 
    var touchStartY; 
    var currentX; 
    var currentY; 
    var shouldMove = false; 
    document.addEventListener(touchstart, swipeStart, false); 
    function swipeStart(event){ 

     touch = realEventType(event); 

     touchStartX = touch.pageX; 
     touchStartY = touch.pageY; 
     var pos = $("#wrapper").position(); 
     currentX = parseInt(pos.left); 
     currentY = parseInt(pos.top); 

     shouldMove = true; 

    } 

    // Touch Move 
    // ------------------------------------------------------------------------------------------ 

    var touchMoveX; 
    var touchMoveY; 
    var distanceX; 
    var distanceY; 
    document.addEventListener(touchmove, swipeMove, false); 
    function swipeMove(event){ 
     if(shouldMove){ 
      touch = realEventType(event); 
      event.preventDefault(); 

      touchMoveX = touch.pageX; 
      touchMoveY = touch.pageY; 

      distanceX = touchMoveX - touchStartX; 
      distanceY = touchMoveY - touchStartY;  
      movePanels(distanceX); 

     } 
    } 

    function movePanels(distance){ 
     newX = currentX + (distance/4);  
     $("#wrapper").css("left", newX); 
    } 


    // Touch End 
    // ------------------------------------------------------------------------------------------ 

    var cutOff = 100; 
    var panelIndex = 0; 
    document.addEventListener(touchend, swipeEnd, false); 
    function swipeEnd(event){ 

     touch = (touchSupport) ? event.changedTouches[0] : event; 

     var touchEndX = touch.pageX; 
     var touchEndY = touch.pageY; 

     updatePanelIndex(distanceX); 

     gotToPanel(); 

     shouldMove = false; 

    } 

    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

    function updatePanelIndex(distance){ 

     if(distanceX > cutOff) 
      panelIndex -= 1; 

     if(distanceX < (cutOff * -1)){ 
      panelIndex += 1; 
     } 

     if(panelIndex < 0){ 
      panelIndex = 0; 
     } 

     if(panelIndex >= panelTotal) 
      panelIndex = panelTotal -1; 

      console.log(panelIndex); 

    } 

    // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

    function gotToPanel(){ 

     var panelPos = getTotalWidthOfElement($(".panel")) * panelIndex * -1; 

     $("#wrapper").css("-webkit-transition-property", "translateX"); 
     $("#wrapper").css("-webkit-transition-duration", "1s"); 
     $("#wrapper").css("-webkit-transform", "translateX("+panelPos+"px)"); 

    } 

}); 

function realEventType(event){ 
    e = (touchSupport) ? event.targetTouches[0] : event; 
    return e; 
} 

回答

8

使用translate3d而不是平移X嘗試。看來只有translate3d在iPad 3.2上進行了硬件加速。

5

如上所述,最好使用Translate3d,因爲硬件加速可以實現更平滑的轉換。

但是,當動畫的div大於屏幕時會引起閃爍。因此,如果你有加起來您希望水平過渡3.5屏幕寬度的區域中,它應該被分解成4個格這樣

[1] [2] [3] [5]

沒有一個div應該超過屏幕的高度或寬度。

對不起,發佈此答案的時間已晚。直到我剛剛收到「熱門問題」通知時,我完全忘記了它。

+0

龐大的 - 我遇到了同樣的問題,但我不知道我知道這個答案。我有一個類似的佈局 - 一個寬度爲視區/屏幕寬度300%的廣視角區域,並且我將該區域左右移動。如果我將它分成3個div,每個div都與屏幕一樣寬 - 那麼你是否建議我單獨爲每個動畫製作動畫? – mattstuehler 2011-04-28 13:01:34

1

通過首先讓視圖處於「3D」狀態,我得到了閃爍消失。首先,我有我的所有意見都有保留-3D。然後,我有這樣的代碼,

MyNamespace.flickerFixer = function(children) { 
children.css({ 
    "-webkitTransform": "translate3D(0px, 0px, 0px)", 
    "-webkit-transition": "1s ease-in-out" 
}); 
} 

然後我做WebKit的動畫之前初始化:

MyNamespace.flickerFixer($this.parent(".ui-content")); 
45

@gargantaun是正確的,Webkit的閃爍,如果你想進行動畫處理的元素比屏幕大。但是有一個簡單的解決方法。只需添加:

-webkit-backface-visibility: hidden; 

給元素,你很好去!

+0

我很好奇,你是怎麼弄出來的? – gargantuan 2011-11-18 12:02:41

+0

發現它[這裏](http://stackoverflow.com/questions/3461441/prevent-flicker-on-webkit-transition-of-webkit-transform),需要它爲我們的[公司網站](http:// www .beenetwork.eu)(等待動畫幾秒鐘)。 – 2011-11-18 12:31:50

+9

使用需要您自擔風險! IOS7出來時,我們的應用程序由於內存錯誤而開始崩潰。它通常使用10-15 MB,但IOS崩潰日誌報告使用約600 MB。經過一番挖掘之後,事實證明,這種背面知名度黑客(我們從源代碼中直接鏈接到這個SO線程)是原因,或者至少是刪除它,導致崩潰消失。不知道爲什麼,它只是IOS7。我認爲在Apple的Webkit分支中必定存在一些內存泄漏漏洞。許多開發者抱怨IOS7 Safari現在崩潰了。 – greim 2013-10-29 22:24:49

1

現在,在iOS8中,另一個很好的解決方案是將overflow: hidden應用於有罪的元素(或其容器)。

0

基於@tobiasahlin在WebExpo上發表演講。

Safari的閃爍問題解決最好的解決辦法是

transform: translateZ(0);