Html 使用 Webkit 转换和转换时如何修复闪烁
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2975217/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to fix flicker when using Webkit transforms & transitions
提问by gargantuan
I have a very simple demo working that uses Webkit transforms and transitions for smooth horizontal scrolling between 'panels' (divs).
我有一个非常简单的演示工作,它使用 Webkit 转换和过渡在“面板”(div)之间进行平滑的水平滚动。
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.
我想走这条路线而不是 Javascript 驱动系统的原因是它是针对 iPad 的,Javascript 性能很差,但是 css 转换和过渡像丝绸一样平滑。可悲的是,我的演示在 iPad 上出现了很多闪烁。
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.
您需要 safari 或 iPad 才能看到它的运行情况。我从未在任何转换和过渡演示中看到这种情况发生,所以我希望这是可以修复的。
Anyway here's the code that powers the thing....
无论如何,这是为这件事提供动力的代码......
The HTML looks like this.
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>
The CSS looks like this
CSS看起来像这样
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
和 javascript 看起来像这样
// 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;
}
采纳答案by Nate T
Try using translate3d instead of translateX. It appears only translate3d is hardware accelerated on iPad 3.2.
尝试使用 translate3d 而不是 translateX。似乎只有 translate3d 在 iPad 3.2 上是硬件加速的。
回答by Mario Uher
@gargantaun is right, Webkit flickers if the element you want to animate is bigger than the screen. But there is an easy fix. Just add:
@gargantaun 是对的,如果要设置动画的元素大于屏幕,Webkit 会闪烁。但是有一个简单的解决方法。只需添加:
-webkit-backface-visibility: hidden;
to the element and you are good to go!
到元素,你很高兴去!
回答by gargantuan
As mentioned above, it is better to use Translate3d due to the hardware acceleration which makes for smoother transitions.
如上所述,由于硬件加速可以实现更平滑的过渡,因此最好使用 Translate3d。
However, the flicker is caused when the div being animated is larger than the screen. So, if you have an area that adds up to 3.5 screen widths that you wish to transition horizontally, it should be broken up into 4 divs like this
但是,当正在设置动画的 div 大于屏幕时会导致闪烁。因此,如果您希望水平过渡的区域加起来多达 3.5 个屏幕宽度,则应将其分解为 4 个 div,如下所示
[ 1 ][ 2 ][ 3 ][.5]
[ 1 ][ 2 ][ 3 ][.5]
None of the divs should exceed the screens height or width.
任何 div 都不应超过屏幕高度或宽度。
Sorry for the lateness in posting this answer. I'd completely forgotten about it until I just got a "popular question" notice.
很抱歉发布此答案的迟到。我完全忘记了它,直到我收到一个“热门问题”通知。
回答by Alex Grande
I got the flicker to go away by first getting the view to be in a "3D" state. First I have all my views have the preserve-3D on. Then I have this code,
我首先让视图处于“3D”状态,从而消除了闪烁。首先,我的所有视图都启用了preserve-3D。然后我有这个代码,
MyNamespace.flickerFixer = function(children) {
children.css({
"-webkitTransform": "translate3D(0px, 0px, 0px)",
"-webkit-transition": "1s ease-in-out"
});
}
And then I initialize it before doing webkit animations:
然后我在做 webkit 动画之前初始化它:
MyNamespace.flickerFixer($this.parent(".ui-content"));
回答by Francesco Frapporti
Nowadays, with iOS8, another good solution is to apply a overflow: hidden
to the incriminated elements (or their container).
如今,在 iOS8 中,另一个好的解决方案是将 a 应用于被控overflow: hidden
元素(或它们的容器)。
回答by Adam ?ír
Based on @tobiasahlintalk at WebExpo.
基于WebExpo上的@tobiasahlin谈话。
Safari flickering issue fix best solution is
Safari 闪烁问题的最佳解决方案是
transform: translateZ(0);
回答by learncodes123
I have found that translate3D is a better solution than animating left: or right: classes. It works well on safari and is smoother. I was having major flickering issues even on iOS13.
我发现 translate3D 是比动画 left: 或 right: 类更好的解决方案。它在 safari 上运行良好,并且更流畅。即使在 iOS13 上,我也遇到了严重的闪烁问题。
This is a slide out:
这是一张幻灯片:
.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);
}
}