2010-06-04 5 views
19

J'ai une démo très simple qui utilise des transformations et des transitions Webkit pour un défilement horizontal fluide entre les 'panneaux' (divs).Comment réparer le flicker lors de l'utilisation des transformations et transitions Webkit

La raison pour laquelle je veux aller dans cette voie par opposition à un système piloté par Javascript est que pour l'iPad et la performance Javascript est assez pauvre, mais les transformations CSS et les transitions sont lisses comme de la soie. Malheureusement, je reçois beaucoup de scintillement sur l'iPad avec ma démo.

Vous pouvez voir the demo here

Vous aurez besoin d'un safari ou iPad et pour le voir en action. Je n'ai jamais vu cela se produire dans l'une des démos pour les transformations et les transitions, donc j'espère que c'est réparable.

Quoi qu'il en soit, voici le code qui alimente la chose ....

Le code HTML ressemble à ceci.

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

Le CSS se présente comme suit

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

et le javascript ressemble à ceci

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

Répondre

8

Essayez d'utiliser translate3d au lieu de translateX. Il semble que translate3d soit accéléré par le matériel sur l'iPad 3.2.

5

Comme mentionné ci-dessus, il est préférable d'utiliser Translate3d en raison de l'accélération matérielle qui permet des transitions plus douces.

Cependant, le scintillement est provoqué lorsque la div animée est plus grande que l'écran. Donc, si vous avez une zone qui ajoute jusqu'à 3,5 largeurs d'écran que vous souhaitez passer à l'horizontale, il doit être divisé en 4 divs comme celui-ci

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

Aucune des divs ne doit dépasser la hauteur ou la largeur des écrans.

Désolé pour le retard dans l'affichage de cette réponse. Je l'avais complètement oublié jusqu'à ce que je reçoive un avis de «question populaire».

+0

gargantuesque - Je suis en cours d'exécution dans le même problème, mais je ne suis pas sûr que je comprends cette réponse. J'ai une disposition similaire - une zone de visualisation large qui est 300% aussi large que la fenêtre/l'écran, et j'anime cette zone à gauche et à droite. Si je divise cela en 3 divs, chacun aussi large que l'écran - alors suggérez-vous que j'anime chacun individuellement? – mattstuehler

1

J'ai obtenu que le scintillement disparaisse en obtenant d'abord que la vue soit dans un état "3D". D'abord, j'ai tous mes points de vue sur la préservation-3D. Ensuite, j'ai ce code,

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

Et puis je l'initialiser avant de faire des animations WebKit:

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

@gargantaun est juste, Webkit scintille si l'élément que vous souhaitez animer est plus grand que l'écran. Mais il y a une solution facile. Il suffit d'ajouter:

-webkit-backface-visibility: hidden; 

à l'élément et vous êtes bon pour vous!

+0

Je suis curieux, comment avez-vous compris cela? – gargantuan

+0

Trouvé [ici] (http://stackoverflow.com/questions/3461441/prevent-flicker-on-webkit-transition-of-webkit-transform), en avait besoin pour notre [site web d'entreprises] (http: // www .beenetwork.eu) (attendez quelques secondes pour l'animation). –

+9

Utilisez à vos risques et périls! Lorsque IOS7 est sorti, notre application a commencé à se bloquer en raison d'erreurs de mémoire. Il utilise normalement 10-15 Mo, mais les journaux de plantage IOS ont signalé l'utilisation de ~ 600 Mo. Après quelques recherches, il s'est avéré que ce hack backface-visibility (que nous avons littéralement un lien vers ce thread SO de notre code source) en était la cause, ou du moins, le supprimait faisait disparaître le crash. Je ne sais pas pourquoi, et c'était seulement IOS7. Je pense qu'il doit y avoir un bug de fuite de mémoire ou quelque chose dans la fourchette de Webkit d'Apple. Beaucoup de développeurs se plaignent du crash de Safari IOS7 de nos jours. – greim

1

De nos jours, avec iOS8, une autre bonne solution consiste à appliquer un overflow: hidden aux éléments incriminés (ou à leur conteneur).

0

Basé sur @tobiasahlin de parler à WebExpo.

Safari question vacillante fixer la meilleure solution est

transform: translateZ(0); 
Questions connexes