CSS硬件加速宽度?

时间:2013-03-27 21:58:01

标签: javascript jquery css css3 hardware-acceleration

我正在尝试构建一个Phonegap应用程序,允许用户通过移动中间分隔符来更改两列布局的大小。

我能够让这个工作,但有一个巨大的UX问题:它是滞后的。这并不可怕,但在最新的iPad上,它甚至引人注目,让我担心。

这是我调整大小的JS:

$("div").on("touchmove", "#columnResizeIcon", function(e) {
    e.preventDefault();
    var left = e.originalEvent.touches[0].pageX;
    var right = $("#columnContainer").width() - left;

    $("#leftColumn").css({
       "width":left - 1 + "px",
       "right":"auto",
    });
    $("#rightColumn").css({
       "width":right - 1 + "px",
       "left":"auto",
    });
    $("#columnResize").css({
       "-webkit-transform":"translate3d(" + left  + "px" + ", 0, 0)",
       "left":"auto",
    });
    $("#columnResizeIcon").css({
       "-webkit-transform":"translate3d(" + left  + "px" + ", 0, 0)",
       "left":"auto",
    });
}); 

您会注意到我利用translate3d()来更改元素的“左”值,因为这是硬件加速。我相信滞后是通过改变左右列的宽度产生的,这就是我需要硬件加速的。

我认为可能有效的解决方案是使用-webkit-transform:translate3d(50%, 0, 0)将右列推到页面的一半以上,然后只更改该值,希望它只会延伸到达父级。然而,它继续,并且占据了50%的页面,而不是父母的50%。

我的HTML标记如下所示:

<div id="columnContainer">
    <div id="columnResize"></div>
    <div id="columnResizeIcon"></div>

    <div id="leftColumn">
        <div class="header">Left Header</div>
        <div class="content"></div>

    </div>
    <div id="rightColumn">
        <div class="header">Right Header</div>
        <div class="content"></div>
    </div>
</div>

我的CSS:

body{
    background-color:#000;
}

#columnContainer{
    position: absolute;
    bottom:0;
    top:0;
    right:0;
    left:0;
    background-color:#000;
}

#leftColumn{
    position: absolute;
    top:0;
    left:0;
    right:50%;
    bottom:0;
    -webkit-overflow-scrolling: touch;
    z-index: 1;
    margin-right: 1px;
}

#rightColumn{
    position: absolute;
    top:0;
    left:50%;
    right:0;
    bottom:0;
    -webkit-overflow-scrolling: touch;
    z-index: 1;
    margin-left: 1px;
}

.header{
    position: absolute;
    left:0;
    right:0;
    height:33px;
    z-index: 5;
    background: -webkit-linear-gradient(top, #f4f5f7 0%,#a7abb7 100%);
    box-shadow:  inset 0 1px 0 #fff, inset 0 -1px 0 #7A8090, 3px 0 2px rgba(0,0,0,.3);
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
    font-size: 17px;
    font-family: Helvetica;
    font-weight: bold;
    letter-spacing: .2px;
    text-align: center;
    padding-top:9px;
    color:#71787F;
    text-shadow: 0 1px 0 #E3E5E9;
}

.content{
    position: absolute;
    left:0;
    right: 0;
    top:42px;
    bottom: 0;
}

#leftColumn .content{
    background-color:#F5F5F5;
}

#rightColumn .content{
    background-color:#fff;
}

#columnResize{
    position: absolute;
    width:2px;
    top:0;
    bottom: 0;
    left:50%;
    margin-left:-1px;
    background-color:#000;
    z-index: 2;
}

#columnResizeIcon{
    position: absolute;
    z-index: 3;
    width:10px;
    height:30px;
    top:50%;
    bottom:50%;
    margin-top:-15px;
    left:50%;
    margin-left:-7px;
    border-left:2px solid #000;
    border-right:2px solid #000;
}

2 个答案:

答案 0 :(得分:2)

我终于想出了一个比我的解决方案更好的解决方案。基本上,我为容器设置了动画,我在调整大小时隐藏了内容。然后,当调整大小完成后,我再次显示内容。我隐藏/显示时使用动画使其看起来很漂亮。代码将比我更好地解释它:

全能小提琴

1 http://jsfiddle.net/charlescarver/hnQHH/134/

我的解释

当点击滑块时,它会使用translate3d()变换将所有文本元素推离页面,然后隐藏div。这是因为如果我在显示元素时尝试更新宽度,则会返回滞后。因此,一旦隐藏了div,我就可以再次使用translate3d()转换向左或向右移动列。我可以在不使每个元素的宽度停止的情况下执行此操作,因为我将leftright值设置为永远无法达到的值,因此它会延伸到页面之外。这样,我可以简单地改变它而不用担心它会过早地切断。

怪诞

有些部分可能是多余的,但我会尽快清理它们。你也可能会注意到一些奇怪的事情,例如(1)cornerLeft,(2)dummy,(3)shadow,以及JS,(4){ {1}}:

  1. 当我调整页面大小时,minimum导航栏会扩展左右列的整个宽度,这意味着它会占据宽度的1000%。这意味着我无法在每个列的左侧和右侧的导航栏上设置dummy,因为它离屏幕太远,以至于它不可见。所以,我做了一个简单的角落来掩盖窗户的每一面,使它看起来很漂亮。

  2. 我调整时会隐藏border-radius.contentLeft,因为它会在显示时导致延迟。我不想摆脱导航栏,所以我创建一个始终在页面上的.contentRight,并且在调整大小即将发生时简单地显示。我认为这减少了滞后,因为我不必添加元素,因为它始终存在。

  3. 然而,一个问题是,当普通导航覆盖虚拟导航时,dummy重叠,导致它变暗,持续200ms。我不喜欢这个。因此,无论导航显示的是什么,我都会在导航的顶部放置一个阴影。

  4. 我现在可以轻松设置可拖动列在停止之前可以达到的界限。方便,对吗?

  5. 代码

    HTML:

    box-shadow

    CSS:

    <div id="container">
        <div class="cornerLeft"></div>
        <div class="cornerRight"></div>
        <div class="shadow"></div>
        <div class="left">
            <div class="contentLeft">
                <div class="header"></div>
                <div class="headerbehind"></div>
                <div class="text textLeft">Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus.</div>
            </div>
            <div class="dummy"></div>
            <div class="dummybg"></div>
        </div>
        <div class="divider"></div>
        <div class="right">
            <div class="contentRight">
                <div class="header"></div>
                <div class="headerbehind"></div>
                <div class="text textRight">Praesent id metus massa, ut blandit odio. Proin quis tortor orci. Etiam at risus et justo dignissim congue. Donec congue lacinia dui, a porttitor lectus.</div>
            </div>
            <div class="dummy"></div>
            <div class="dummybg"></div>
        </div>
    </div>
    

    JS:

    * {
        -webkit-text-size-adjust:none;
    }
    #container {
        position:fixed;
        left:0;
        right:0;
        bottom:0;
        top:0;
        background-color:#000;
        -webkit-transform: translateZ(0);
        -webkit-perspective: 1000;
    }
    .left {
        -webkit-transform:translate3d(0, 0, 0);
        position:absolute;
        left:-3000px;
        right:50%;
        top:0;
        bottom:0;
        border-right:1px solid #000;
        -webkit-perspective: 1000;
        -webkit-backface-visibility: hidden;
    }
    .right {
        -webkit-transform:translate3d(0, 0, 0);
        position:absolute;
        left:50%;
        right:-3000px;
        top:0;
        bottom:0;
        border-left:1px solid #000;
        -webkit-perspective: 1000;
        -webkit-backface-visibility: hidden;
    }
    .divider {
        width:24px;
        height:40px;
        border-left:2px solid #000;
        border-right:2px solid #000;
        position:absolute;
        left:50%;
        z-index:3;
        margin-left:-14px;
        margin-top:-20px;
        top:50%;
        -webkit-transform:translate3d(0, 0, 0);
        -webkit-perspective: 1000;
        -webkit-backface-visibility: hidden;
        -webkit-touch-callout: none;
        -webkit-user-select: none;
    }
    .contentLeft {
        position:absolute;
        right:0;
        bottom:0;
        top:0;
        -webkit-transform: translateZ(0);
        -webkit-perspective: 1000;
        -webkit-backface-visibility: hidden;
    }
    .contentRight {
        position:absolute;
        left:0;
        bottom:0;
        top:0;
        -webkit-transform: translateZ(0);
        -webkit-perspective: 1000;
        -webkit-backface-visibility: hidden;
    }
    .cornerLeft:after {
        content:"";
        height:5px;
        position:absolute;
        left:0;
        width:5px;
        background: -webkit-linear-gradient(top, #F0F2F4 0%, #EAEBEE 100%);
        z-index:700;
        border-top-left-radius:5px;
        box-shadow:inset 0 1px 0 #fff;
    }
    .cornerLeft {
        position:absolute;
        z-index:700;
        left:0;
        width:5px;
        height:5px;
        background-color:#000;
    }
    .cornerRight:after {
        content:"";
        height:5px;
        position:absolute;
        right:0;
        width:5px;
        background: -webkit-linear-gradient(top, #F0F2F4 0%, #EAEBEE 100%);
        z-index:700;
        border-top-right-radius:5px;
        box-shadow:inset 0 1px 0 #fff;
    }
    .cornerRight {
        position:absolute;
        z-index:700;
        right:0;
        width:5px;
        height:5px;
        background-color:#000;
    }
    .header, .dummy {
        position: absolute;
        left:0;
        right:0;
        height:35px;
        background: -webkit-linear-gradient(top, #f4f5f7 0%, #a7abb7 100%);
        border-top-left-radius: 5px;
        border-top-right-radius: 5px;
        font-size: 17px;
        font-family: Helvetica;
        font-weight: bold;
        letter-spacing: .2px;
        text-align: center;
        padding-top:9px;
        color:#71787F;
        text-shadow: 0 1px 0 #E3E5E9;
        word-break: break-all;
        box-shadow:inset 0 1px 0 #fff, inset 0 -1px 0 #7A8090;
    }
    .shadow {
        height:44px;
        position:absolute;
        left:0;
        right:0;
        box-shadow:0 1px 2px rgba(0, 0, 0, .2);
        z-index:600;
    }
    .header {
        z-index:500;
    }
    .dummy {
        z-index:100;
    }
    .headerbehind {
        position:absolute;
        background-color:#000;
        left:0;
        right:0;
        height:44px;
        z-index:499;
    }
    .text, .dummybg {
        margin-top:44px;
        background-color:#fff;
        position:absolute;
        top:0;
        right:0;
        left:0;
        bottom:0;
    }
    .text {
        z-index:2;
        padding:20px 40px;
        -webkit-animation-duration:200ms;
        -webkit-animation-timing-function:ease;
    }
    .contentLeft, .contentRight {
        z-index:300;
    }
    .leftOut {
        -webkit-transform:translate3d(-100%, 0, 0);
        -webkit-animation-name:leftOut;
        -webkit-perspective: 1000;
        -webkit-backface-visibility: hidden;
    }
    .leftIn {
        -webkit-transform:translate3d(0, 0, 0);
        -webkit-animation-name:leftIn;
        -webkit-perspective: 1000;
        -webkit-backface-visibility: hidden;
    }
    @-webkit-keyframes leftOut {
        0% {
            -webkit-transform:translate3d(0, 0, 0);
        }
        100% {
            -webkit-transform:translate3d(-100%, 0, 0);
        }
    }
    @-webkit-keyframes leftIn {
        0% {
            -webkit-transform:translate3d(-100%, 0, 0);
        }
        100% {
            -webkit-transform:translate3d(0, 0, 0);
        }
    }
    .rightOut {
        -webkit-transform:translate3d(100%, 0, 0);
        -webkit-animation-name:rightOut;
    }
    .rightIn {
        -webkit-transform:translate3d(0, 0, 0);
        -webkit-animation-name:rightIn;
    }
    @-webkit-keyframes rightOut {
        0% {
            -webkit-transform:translate3d(0, 0, 0);
        }
        100% {
            -webkit-transform:translate3d(100%, 0, 0);
        }
    }
    @-webkit-keyframes rightIn {
        0% {
            -webkit-transform:translate3d(100%, 0, 0);
        }
        100% {
            -webkit-transform:translate3d(0, 0, 0);
        }
    }
    

    1 是的,我花了134次尝试。

答案 1 :(得分:0)

通过在硬件加速堆栈中对这两个元素提出质疑,我取得了一些成功:

#leftColumn,
#rightColumn {
  -webkit-transform: translate3d(0,0,0);
} 

似乎要更顺利地调整大小。并不是改变width本身是优化的,而是更快地重新渲染元素本身。

我在这里设置了一个插件:http://plnkr.co/edit/5RMtCl1Sql8f3CmQLHFz