WebKit Translate3d问题(窥视)

7
我正在使用PhoneGap构建iOS应用程序。我使用translate3d CSS动画来创建“翻转”效果。
这在简单的元素上运行得很好...一个带有前/后div和可能有一两个额外span的DIV。
但是当我尝试翻转一个更大的元素...即整个屏幕时,我会遇到重绘故障。当我交换css类以开始过渡时,'底部' div的某些部分会穿过'顶部' div,然后发生翻转,然后它们再次弹出。而且不是整个元素都显示出来...它沿着我进行translate3d旋转的轴分成了元素的一半。
对于可能导致此问题的原因或理论有任何想法吗?它在iPad上作为应用程序和在Safari中的桌面上都是相同的,因此似乎是Webkit问题。
这可能是一些CSS问题吗?还是尝试使用具有大型背景图像的复杂嵌套元素进行全屏translate3d旋转只是超出了Safari的处理能力?
更新1:
我已经在缩小问题范围方面取得了进展。
正在发生的事情是,当我执行translate3d翻转时,“窥视”的元素恰好是之前通过translate3d定位的子元素。
我要使用translate3d过渡的“页面”结构:
<div id="frontbackwrapper">
    <div id="front">    
    </div><!--/front-->
    <div id="back">  
    </div><!--/back-->
</div><!--/frontbackwrapper-->  

这个可以单独工作。前面的div会用卡片翻转效果替换为后面的div。

问题在于,在进行整个页面翻转之前,我已经使用translate3d动画了#front div中的一些元素:

<div id="frontbackwrapper">
    <div id="front">  

        <div class="modal"></div>  

    </div><!--/front-->
    <div id="back">  
    </div><!--/back-->
</div><!--/frontbackwrapper--> 

示例CSS:

.modal {
    width: 800px;
    height: 568px;
    position: absolute; 
    left: 112px;
    z-index: 100;
    -webkit-transition-duration: 1s;
    -webkit-transform: translate3d(0,-618px,0); /* set off screen by default */
 }
.modal.modalOn {
    -webkit-transform: translate3d(0,80px,0); /* slides the div into place */
 }

如果我不使用 translate3d,而是用 top 样式重新定位 div 或者改变 top 属性,我就不会出现窥视问题。当然,这意味着我必须分别放弃流畅的动画或硬件加速。
此时,看起来像是一个 Webkit 的 bug。我将继续尝试解决。如果有人遇到过这个问题并找到了解决方法,我非常乐意听取!
2个回答

6
解决方案!经过一夜的思考,我琢磨出罪魁祸首以及该如何处理。问题并不在于使用translate3d来使子元素动画化,而是被转换的元素在其父元素正在使用translate3d进行动画效果时拥有了该CSS属性。
解决方法是先对子元素进行动画处理,然后完全删除translate样式。
现在的CSS结构如下:
/* default class for the start of your element */
.modal-startposition {
  -webkit-transition-duration: 1s;
  -webkit-transform: translate3d(0,-618px,0);
  }

/* add this class via jQuery to then allow
   webkit to animate the element into position */
.modal-animateposition {
  -webkit-transform: translate3d(0,80px,0);
}

/* when animation is done, remove the above class
   and replace it with this */
.modal-endposition {
  top: 80px;
}

以下是一些jQuery示例:

//[attach a click event to trigger and then...]
$myModal
    .addClass("modal-animateposition")
    .on('webkitTransitionEnd',function () {
         $myModal
            .removeClass('modal-startposition')
            .removeClass('modal-animateposition')
            .addClass('modal-endposition');
    });

有点繁琐,但它完全解决了屏幕重绘问题。
编辑:更正了一个错别字。

@IanJamison 我知道这个答案已经几年了,但我不确定将“one”更改为“on”是否正确。据我所知,“on”基本上与“one”相同(因为一个调用),但它不会在完成时删除事件处理程序。老实说,我不记得在这个特定的应用程序中是否会有所不同,但在某些情况下选择“one”和“on”似乎有非常明确的原因。 - DA.

2

DA,我从中学到了一些东西,感谢。还要注意css属性,'translate3d'和'left'。翻译和定位是有些不同的。试着将一个元素在x轴上平移100像素,并将它的'left'样式属性设置为0像素。验证一下,它将从当前翻译点(从x轴100像素开始)在x轴上被定位在0像素处。

这会在拖放和动画算法中产生数学错误,并且很容易被注意到(重绘故障、跳过、位置重置),因为translate3d不再更新元素的offsetLeft或'left'样式属性(为了优化而防止回流),所以解析元素的实际左侧,基于知道是否使用了translate3d或left。如果你是游戏开发者,追踪内部变量中的x、y值是保持与元素位置同步的方法。希望这能更好地帮助你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接