How to fix flicker when using Webkit transforms & transitions

Posted by gargantaun on Stack Overflow See other posts from Stack Overflow or by gargantaun
Published on 2010-06-04T14:50:20Z Indexed on 2010/06/12 17:22 UTC
Read the original article Hit count: 711

Filed under:
|
|
|

I have a very simple demo working that uses Webkit transforms and transitions for smooth horizontal scrolling between 'panels' (divs).

The reason I want to go this route as opposed to a Javascript driven system is that it's for the iPad and Javascript performance is quite poor, but the css transforms and transitions are smooth as silk. Sadly though, I'm getting a lot of flicker on the iPad with my Demo.

You can see the demo here

You'll need safari or and iPad to see it in action. I've never seen this happening in any of the demos for transforms and transitions so I'm hopeful that this is fixable.

Anyway here's the code that powers the thing....

The HTML looks like this.

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

The CSS looks like this

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

and the javascript looks like this

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

© Stack Overflow or respective owner

Related posts about html

Related posts about css