iPad键盘使用后,CSS3动画闪烁问题

17

我正在使用HTML5/CSS3为iPad开发应用程序。我没有使用任何框架,而是仅使用设备本地支持的内容。我创建了一些CSS3动画来模拟iOS屏幕之间滑动时的典型左滑或右滑。以下是一个滑向左侧的动画示例,它利用了iPad的CSS3硬件加速功能:(iPad运行4.2版本)。

/*************************************************
Slide Left
*************************************************/
.screen.slideleft{
 -webkit-animation-duration: 0.5s;
 -webkit-animation-timing-function: ease-in-out;
}
.screen.slideleft.outgoing{
 z-index: 50 !important;
 -webkit-animation-name: slideleft-outgoing;

}
.screen.slideleft.incoming{
 z-index: 100 !important;
 -webkit-animation-name: slideleft-incoming;
}
@-webkit-keyframes slideleft-outgoing{
 from { -webkit-transform: translate3d(0%,0,0); }
 to { -webkit-transform: translate3d(-100%,0,0); }
}
@-webkit-keyframes slideleft-incoming{
 from { -webkit-transform: translate3d(100%,0,0); }
 to { -webkit-transform: translate3d(0%,0,0); }
}

我还有这段CSS,我试图使用它来修复闪烁问题:

.incoming,
.outgoing{
 display: block !important;
 -webkit-backface-visibility: hidden;
}

这很有效,但是当iPad键盘被使用后,所有的动画都会严重闪烁。

我一直在寻找一个使用键盘并且之后没有闪烁的iPad HTML5应用程序的例子,但是没有找到太多。 jqTouch演示在iPad上表现出相同的行为(尽管我知道它们是为iPhone设计的)。

我找到了一些类似的帖子/问题,但没有找到好的答案。 我已经阅读了http://css3animator.com/2010/12/fight-the-flicker-making-your-css3-animation-bomb-proof/和那里链接的文章,但没有成功。

还有其他建议吗?

更新1/13 @ 9am

我添加了这个CSS,它帮助了很多:

.incoming *,
.outgoing *{
 -webkit-backface-visibility: hidden;
 -webkit-transform: translate3d(0,0,0); /* 这可以显著减少闪烁。 */
}

前景元素似乎不再闪烁,但背景仍然会。仍在寻找一些有关Mobile Safari内存处理策略的帮助或有用资源。

更新1/16 @ 11pm

按照匿名建议增加z-index,但似乎没有什么区别。

更新 1/17 @ 8:30am

我在这里发布了一个问题演示。

在屏幕之间的转换很好...直到您在其中一个表单字段内点击。键盘弹出并返回后,所有转换都会闪烁。在iOS模拟器或实际iPad上打开链接以查看我所说的内容。


我仍在寻找任何有用的建议! - Daniel
为了寻求帮助解决这个问题,我将发起一个悬赏。 - Daniel
8个回答

4
这是一个老问题,但我想分享我的经验。
在iPad上(以及iPhone上,在那种情况下仅在纵向视图中)我一直遇到CSS3动画中的惊人闪烁问题。通过设置以下内容,我能够完全解决所有闪烁问题:
-webkit-perspective: 0; 

在进行动画的元素上。我不确定为什么这样可以,但它确实可以(已在iOS 4.2+,iPad(1和2)和iPhone 4上测试)。

更新:当将该属性的值设置为1时,我刚刚意识到在Chrome上存在一个问题。 当其为0时,它可以正常工作,因此我已相应地更新了上述内容。


1

看了你的代码,translate3d(0,0,0)是在过渡开始时才应用的吗?

试试这样:

.screen{
    -webkit-transform: translate3d(0,0,0);
}

或者

.screen *, .screen{
        -webkit-transform: translate3d(0,0,0);
}

闪烁问题可能是硬件加速启动了(目前仅适用于3D转换元素)。


我最初把它设置为 only translateX 而不是 translate3d;我改为使用 translate3d 以启用硬件加速,但无论哪种方式都会闪烁。然而,只有在使用键盘后才会出现这个问题——在使用键盘前一切正常。 - Daniel
1
有趣的是,你的第一个建议 .screen{ -webkit-transform: translate3d(0,0,0); } 确实改善了出屏幕的闪烁。而第二个建议则使情况变得更糟——我怀疑这是因为每个元素都需要 -webkit-transform: translate3d 所占用的内存太多了。 - Daniel
现在好了吗?还需要微调吗? - Ben Collier
如果完美的话,您可以尝试在出站时使用-webkit-transform: translate3d(0,0,0);,并在入站时使用-webkit-transform: translate3d(100%,0,0); - Ian Storm Taylor

1

我知道这是一个老问题,但是有一个解决方案,它非常轻量级且非常简单。

document.getElementById('clicked_input').addEventListener('focus', function(e){
    e.stopPropagation();
},false);

当我也在解决这个问题时,我认为我尝试了所有的方法 - 最终唯一有用的是创建一个模态窗口(position: absolute)在应用程序容器 div 之外,并在键盘弹出时将应用程序容器 div 设置为 display:false;。虽然它起作用了,但很丑陋,我测试了所有东西以查看是什么导致了事件,似乎当“焦点事件”冒泡时,每个 3D 变换都会混乱(闪烁和性能)。

防止冒泡事件完全解决了这个问题 - 相当让人费解,这样一个被人们所憎恶的 bug 竟然有如此简单的解决方案?


这是一个非常有趣的想法 - 我会记在脑后下次尝试(当然,随着iOS5的推出,WebKit可能会发生什么变化)。 - Daniel

1

我尝试在slide left和slide right上将.outgoing的z-index更改为-1,但在我的情况下它并没有修复(甚至减少)闪烁。 - Daniel

0

我同意Ben的观点,你可能也应该在类本身上设置转换:

/*************************************************
Slide Left
*************************************************/
.screen.slideleft{
 -webkit-animation-duration: 0.5s;
 -webkit-animation-timing-function: ease-in-out;
 -webkit-transform: translate3d(0,0,0);
}
.screen.slideleft.outgoing{
 z-index: 50 !important;
 -webkit-animation-name: slideleft-outgoing;
 -webkit-transform: translate3d(-100%,0,0);
}
.screen.slideleft.incoming{
 z-index: 100 !important;
 -webkit-animation-name: slideleft-incoming;
 -webkit-transform: translate3d(0,0,0);
}
@-webkit-keyframes slideleft-outgoing{
 from { -webkit-transform: translate3d(0,0,0); }
 to { -webkit-transform: translate3d(-100%,0,0); }
}
@-webkit-keyframes slideleft-incoming{
 from { -webkit-transform: translate3d(100%,0,0); }
 to { -webkit-transform: translate3d(0,0,0); }
}

如果这样不起作用,我很想测试一下只将X翻译为translateX(-100%)是否可以解决问题。(不一定是解决方案,因为没有3D变换就没有硬件加速,但可以帮助缩小问题范围。)

我最初将其命名为translateX,后来改为translate3d以启用硬件加速。但无论哪种方式都没有什么区别。我尝试添加translate3d并移动其他元素,但只有轻微的成功。请参见我对Ben建议的评论。 - Daniel

0

最近我也遇到了同样的问题,尝试了各种复杂的解决方法。最终我发现问题出在输入框的默认样式上。我通过添加CSS input{outline:none} 来解决我的问题。这可能只是在焦点状态下,所以input:focus{outline:none;} 应该可以解决。


0

我知道你可能不喜欢听这个,但JavaScript可能是你正在寻找的答案。我担心当你打开键盘时,渲染HTML的过程会失去优先级。使用一个不断更新的脚本,比如setInterval循环,iPad将不得不按计划进行渲染。显式代码不需要任何黑客技巧。


我可能误解了你的意思,但在这种情况下,我没有使用任何类型的setInterval或setTimeout - 我完全依靠CSS变换进行动画。这些转换在iPad上具有硬件加速。任何与闪烁相近的JavaScript都只是添加一个或两个类。 - Daniel
1
为了清晰起见,在键盘返回之后很长一段时间仍会出现闪烁。 - Daniel
我想说的是,也许问题在于你没有使用JavaScript。CSS由浏览器异步渲染,这会导致较大的错误窗口。在你的情况下,Safari存在冲突事件,导致闪烁。虽然可能会稍微影响性能,但如果你使用JavaScript控制菜单/小部件/滑块或其他名称,就可以消除闪烁。 - Anonymous
对不起,我误解了整件事情。我以为这是关于CSS动画的。这是CSS3D?你遇到了一个z缓冲问题。我建议增加你使用的单位的大小。让所有东西分开一些。 - Anonymous
我将传入的 z-index 更改为 100 而不是 50(我已更新上面的 CSS),但没有任何变化。明天我会发布一个示例,以便人们可以看到发生了什么。 - Daniel
显示剩余5条评论

0

最终,这个问题似乎没有解决方案。在iPad上,WebKit中的表单元素似乎会导致闪烁问题。

我的解决方法是,在每个表单元素的onblur事件中,使用哈希标签刷新页面,以确保它刷新到完全相同的状态。虽然在刷新时仍会出现“闪烁”,但它确实可以防止整个应用程序屏幕闪烁。


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