Html 如何修复使用Webkit变换时的闪烁&;过渡

Html 如何修复使用Webkit变换时的闪烁&;过渡,html,css,safari,webkit,Html,Css,Safari,Webkit,我有一个非常简单的演示,它使用Webkit变换和转换在“面板”(div)之间平滑地水平滚动 我之所以要走这条路,而不是Javascript驱动的系统,是因为它适用于iPad,Javascript性能相当差,但css转换和转换非常平滑。遗憾的是,我的演示在iPad上出现了很多闪烁 你可以看到 你需要safari或iPad才能看到它的运行。我从未在任何变换和转换的演示中看到过这种情况,所以我希望这是可以解决的 不管怎么说,这是为这件事提供动力的代码 HTML如下所示 <html>

我有一个非常简单的演示,它使用Webkit变换和转换在“面板”(div)之间平滑地水平滚动

我之所以要走这条路,而不是Javascript驱动的系统,是因为它适用于iPad,Javascript性能相当差,但css转换和转换非常平滑。遗憾的是,我的演示在iPad上出现了很多闪烁

你可以看到

你需要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>
javascript看起来是这样的

    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;
        }
// 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;
}
//鼠标/iPad触摸屏
var touchSupport=(触摸类型=“对象”),
touchstart=touchSupport?“touchstart':'mousedown',
touchmove=touchSupport?“touchmove':'mousemove',
touchend=touchSupport?“touchend':'mouseup';
$(文档).ready(函数(){
//将顶部和左侧设置为零
$(“#包装器”).css(“顶部”,0);
$(“#包装器”).css(“左”,0);
//获取面板的总数
总风险价值;
$(“.panel”).each(函数(){panelTotal+=1});
//触式起动
// ------------------------------------------------------------------------------------------
var-touchtartx;
var触摸屏;
无功电流x;
无功电流;
var shouldMove=false;
文档。addEventListener(touchstart、swipeStart、false);
功能启动(事件){
触摸=realEventType(事件);
touchStartX=touch.pageX;
touchStartY=touch.pageY;
var pos=$(“#包装器”).position();
currentX=parseInt(位置左侧);
currentY y=parseInt(位置顶部);
shouldMove=true;
}
//触动
// ------------------------------------------------------------------------------------------
var-touchMoveX;
var touchMoveY;
var距离;
var距离;
文件。添加的文件列表(touchmove、swipeMove、false);
功能开关移动(事件){
如果(应该移动){
触摸=realEventType(事件);
event.preventDefault();
touchMoveX=touch.pageX;
touchMoveY=touch.pageY;
距离X=触摸移动X-触摸开始X;
distanceY=touchMoveY-touchStartY;
移动面板(距离X);
}
}
功能面板(距离){
newX=电流x+(距离/4);
$(“#包装器”).css(“左”,newX);
}
//接触端
// ------------------------------------------------------------------------------------------
var截止=100;
var指数=0;
文件。添加的监听器(触摸端、开关、假);
功能切换(事件){
触摸=(触摸支持)?事件。更改触摸[0]:事件;
var touchEndX=touch.pageX;
var touchEndY=touch.pageY;
updatePanelIndex(距离X);
gotToPanel();
shouldMove=false;
}
// --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
函数updatePanelIndex(距离){
如果(距离X>截止)
panelIndex-=1;
如果(距离X<(截止*-1)){
指数+=1;
}
如果(面板索引<0){
panelIndex=0;
}
如果(panelIndex>=panelTotal)
panelIndex=panelTotal-1;
console.log(panelIndex);
}
// --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --  --
函数gotToPanel(){
var panelPos=getTotalWidthOfElement($(“.panel”)*panelIndex*-1;
$(“#包装器”).css(“-webkit转换属性”,“translateX”);
$(“#包装器”).css(“-webkit转换持续时间”,“1s”);
$(“#包装器”).css(“-webkit-transform”,“translateX”(+panelPos+“px”);
}
});
函数realEventType(事件){
e=(touchSupport)?事件。targetTouches[0]:事件;
返回e;
}

尝试使用translate3d而不是translateX。似乎只有translate3d在iPad 3.2上是硬件加速的。

如上所述,最好使用translate3d,因为硬件加速有助于更平滑的过渡

但是,当正在设置动画的div大于屏幕时,会导致闪烁。所以,如果你有一个区域,加起来有3.5个屏幕宽度,你希望水平过渡,它应该被分成4个像这样的分区

    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;
        }
// 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;
}
[1][2][3][.5]

所有div均不得超过屏幕高度或宽度


很抱歉延迟发布此答案。我完全忘记了这一点,直到我刚刚收到一个“热门问题”通知。

我首先将视图设置为“3D”状态,从而消除了闪烁。首先,我的所有视图都打开了preserve-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"));

@gargantaun是对的,如果要设置动画的元素比屏幕大,Webkit会闪烁。但有一个简单的解决办法。只需添加:

-webkit-backface-visibility: hidden;

到元素和你是好去

如今,使用iOS8,另一个好的解决方案是将
溢出:隐藏
应用于被指控的元素(或其容器)。

基于WebExpo上的讨论

Safari闪烁问题修复的最佳解决方案是

transform: translateZ(0);

我发现translate3D是比设置左:或右:类动画更好的解决方案。它在safari上运行良好,并且更平滑。即使在iOS13上,我也有一些重大的问题

这是一张幻灯片:

.cartout-enter-active {
  -webkit-animation: cartout 0.2s;
  animation: cartout 0.2s;
}
.cartout-leave-active {
  -webkit-animation: cartout 0.2s reverse;
  animation: cartout 0.15s reverse;
}
@-webkit-keyframes cartout {
  from {
    transform: translate3d(100%, 0, 0);
  }

  to {
    transform: translate3d(0%, 0, 0);
  }
}

庞大-我遇到了同样的问题,但我不确定我是否理解这个答案。我有一个类似的布局-一个宽的可视区域,它的宽度是视口/屏幕的300%,我正在左右设置该区域的动画。如果我把它分成3个分区,每个分区都和屏幕一样宽,那么你是在建议我