2010-06-04 17 views
19

Ho una demo molto semplice che utilizza trasformazioni e transizioni Webkit per uno scorrimento orizzontale uniforme tra "pannelli" (div).Come correggere lo sfarfallio quando si utilizzano trasformazioni e transizioni Webkit

Il motivo per cui voglio percorrere questa rotta rispetto a un sistema basato su Javascript è che è per l'iPad e le prestazioni di Javascript sono piuttosto scadenti, ma le trasformazioni CSS e le transizioni sono fluide come la seta. Purtroppo però ho un sacco di sfarfallio sull'iPad con la mia demo.

Si può vedere the demo here

Avrete bisogno di safari o iPad e per vederlo in azione. Non ho mai visto questo accadere in nessuna delle demo per trasformazioni e transizioni quindi sono fiducioso che sia risolvibile.

Comunque ecco il codice che alimenta la cosa ....

Il codice HTML simile a questo.

<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> 

Il CSS si presenta così

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; 
     } 

e javascript assomiglia a questo

// 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; 
} 

risposta

8

Provate ad usare translate3d invece di translateX. Appare solo translate3d è hardware accelerato su iPad 3.2.

5

Come accennato in precedenza, è meglio utilizzare Translate3d a causa dell'accelerazione hardware che rende più fluide le transizioni.

Tuttavia, lo sfarfallio è causato quando il div che si sta animando è più grande dello schermo. Quindi, se si dispone di una zona che aggiunge fino a larghezze di 3.5 dello schermo che si desidera per la transizione in senso orizzontale, dovrebbe essere suddiviso in 4 divs come questo

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

Nessuno dei div deve superare l'altezza o la larghezza dello schermo.

Ci scusiamo per il ritardo nel pubblicare questa risposta. Mi ero completamente dimenticato di questo fino a quando non ho ricevuto un avviso di "domanda popolare".

+0

pantagruelica - Sono in esecuzione nello stesso problema, ma non sono sicuro di aver capito questa risposta. Ho un layout simile: un'area di visualizzazione ampia, larga al 300% rispetto al viewport/schermo, e sto animando quella zona a destra ea sinistra. Se lo divido in 3 div, ciascuno ampio come lo schermo, allora stai suggerendo di animare ciascuno di essi individualmente? – mattstuehler

1

Ho ottenuto lo sfarfallio di andare via prima ottenere la vista di essere in uno stato "3D". Per prima cosa ho tutte le mie opinioni su come preservare-3D. Poi ho questo codice,

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

E poi ho inizializzarlo prima di fare animazioni WebKit:

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

@gargantaun è giusto, Webkit lampeggia se l'elemento che si desidera animare è più grande dello schermo. Ma c'è una soluzione facile. Basta aggiungere:

-webkit-backface-visibility: hidden; 

per l'elemento e siete a posto!

+0

Sono curioso, come lo hai capito? – gargantuan

+0

Trovato [qui] (http://stackoverflow.com/questions/3461441/prevent-flicker-on-webkit-transition-of-webkit-transform), necessario per il nostro [sito web delle aziende] (http: // www .beenetwork.eu) (aspetta solo pochi secondi per l'animazione). –

+9

Usa a proprio rischio! Quando è uscito IOS7, la nostra app ha iniziato a bloccarsi a causa di errori di memoria. Normalmente utilizza 10-15 MB, ma i registri degli arresti di IOS segnalano l'uso di ~ 600 MB. Dopo alcuni scavi, si è scoperto che questo hack di visibilità sul retro (che abbiamo letteralmente un link a questo thread SO dal nostro codice sorgente) è stata la causa, o almeno, la rimozione ha fatto sparire il crash. Non so perché, ed era solo IOS7. Penso che ci debba essere un bug di perdita di memoria o qualcosa del fork di Apple di Webkit. Al giorno d'oggi molti sviluppatori si lamentano di Safari IOS7. – greim

1

Oggigiorno, con iOS8, un'altra buona soluzione è applicare uno overflow: hidden agli elementi incriminati (o al loro contenitore).

0

Sulla base di @tobiasahlin parlare a WebExpo.

Safari problema sfarfallio fissare migliore soluzione è

transform: translateZ(0); 
Problemi correlati