Как исправить мерцание при использовании преобразований и переходов Webkit
У меня есть очень простая демонстрационная работа, которая использует преобразования и переходы Webkit для плавной горизонтальной прокрутки между "панелями" (divs).
Причина, по которой я хочу пойти по этому пути в отличие от системы, управляемой Javascript, заключается в том, что она для iPad, а производительность Javascript довольно низкая, но преобразования CSS и переходы плавные, как шелк. К сожалению, с моим демо я получаю много мерцания на iPad.
Вы можете увидеть демо здесь
Вам понадобится сафари или 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>
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;
}
и 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;
}
6 ответов
Попробуйте использовать translate3d вместо translateX. Похоже, только translate3d является аппаратно ускоренным на iPad 3.2.
@gargantaun прав, Webkit мерцает, если элемент, который вы хотите анимировать, больше экрана. Но это легко исправить. Просто добавь:
-webkit-backface-visibility: hidden;
к стихии, и вы готовы идти!
Как упоминалось выше, лучше использовать Translate3d из-за аппаратного ускорения, которое обеспечивает более плавные переходы.
Однако мерцание возникает, когда анимация div больше, чем экран. Итак, если у вас есть область шириной до 3,5 экранов, которую вы хотите переместить горизонтально, она должна быть разбита на 4 деления, как это
[ 1 ][ 2 ][ 3 ][.5]
Ни один из элементов div не должен превышать высоту или ширину экрана.
Извините за опоздание в публикации этого ответа. Я полностью забыл об этом, пока не получил уведомление "популярный вопрос".
Я получил мерцание, чтобы уйти, сначала приведя вид в "трехмерное" состояние. Во-первых, у меня есть все мои виды, в которых присутствует 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"));
На основе @tobiasahlin говорить на WebExpo.
Решение проблемы мерцания в Safari - лучшее решение
transform: translateZ(0);
В настоящее время, с iOS8, еще одним хорошим решением является применение overflow: hidden
инкриминированным элементам (или их контейнеру).
Я обнаружил, что translate3D - лучшее решение, чем анимация классов left: или right:. Он хорошо работает на сафари и более плавный. У меня были серьезные проблемы с мерцанием даже на 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);
}
}