2010-06-04 66 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);