我正在尝试在我的网站上制作动画。我正在使用下面链接的类似版本的 jsfiddle 代码。在桌面上查看时,动画效果很好。然而,当在移动设备上查看时,特别是在我的 chrome 浏览器上,会有一个奇怪的延迟。当我在手机上打开 jsfiddle 时,它会显示完全相同的延迟。如果我重新启动 chrome 应用程序,延迟会很快消失。
Safari 中不会出现此问题。
我有最新的带有 IOS 14.6 和 chrome V90 的 iPhone。
https://jsfiddle.net/brodriguez98/e2bvwcja/33/
HTML:
<html>
<p style = 'margin-top: 100vh;'>above</p>
<img class = 'balltest show-on-scroll standard-push' src = 'http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png'/>
<img class = 'balltest show-on-scroll fade-in' src = 'http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png'/>
<p style = 'margin-bottom: 100vh'>below</p>
</html>
CSS:.balltest {
width: 50px;
}
.fade-in {
opacity: 0;
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.standard-push {
opacity: 0;
transform: translateY(4em);
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out, translateZ(0);
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.is-visible {
transform: translateY(0);
opacity: 1;
}
Javascript:var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
Array.prototype.forEach.call(elementsToShow, function (element) {
if (isElementInViewport(element)) {
element.classList.add('is-visible');
} else {
element.classList.remove('is-visible');
}
});
});
// Helper function from: http://stackoverflow.com/a/7557433/274826
function isElementInViewport(el) {
// special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
(rect.top <= 0 &&
rect.bottom >= 0) ||
(rect.bottom >= (window.innerHeight || document.documentElement.clientHeight) &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight)) ||
(rect.top >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight))
);
}
我为小屏幕道歉,无法在我的手机上全屏显示 JSfiddle:动画在重新启动移动 chrome 后立即工作:
https://www.loom.com/share/ac6c843b90d2428bb875572d55e32959
动画很快中断(当我关闭/重新加载页面时):
https://www.loom.com/share/e51cf88aa1a74aed8e4d1ed253e83ea0
这与我在使用移动 chrome 浏览器的网站上看到的行为完全相同。
更新:
下面的答案都不适合我。我忘了提到这种行为也发生在文本中。另外,感谢您建议代码和框,我 fork 了您的代码并通过删除图像使其更加简单,但我仍然在我的 iphone chrome 浏览器上得到相同的结果。我还尝试使用 onload 函数包装所有内容,但这也不起作用。
现在我可以用 JQuery 动画解决这个问题,但我仍然希望 CSS3 过渡在我的网站上工作。
https://codesandbox.io/s/animation-test-forked-tqurn?file=/index.html
最佳答案
加载页面时,这看起来像是“竞争条件”问题。
JS 在 IMG 请求完成之前运行。
要了解问题,有必要了解加载顺序:
如果对 *.js 文件的请求完成 之前 IMG 请求完成,没有呈现
height
找到该图像和新添加的 CSS 类 is-visible
将启动 transition
反正...一个 正在进行的过渡在需要重绘的元素(IMG)上是“重置”并从关键帧 0 开始。
这可以解释你的问题。
这里有 3 个选项可以解决您的问题:
A. 保留图像的最终尺寸。
height
在 CSS 中并在 html 中添加类:.myImg {
width: 50px;
height: 50px;
}
width
和 height
作为html属性。即使 *.css 仍在加载,最终尺寸现在也可以在 JS 中使用...<img height="50" width="50" class="..." src="...">
B. 为图像添加一些“加载检测”,并在图像完全加载之前阻止过渡。
src
设置和height
被检测到- onload
该图像的事件(因为尚未加载)src
设置为 data-src
属性和和 src
一旦图像可用,将由 JS 设置。 现在我们可以使用
isLoaded(element)
排除.scroll()
中的图像的功能当前未满载的。这里是 jsFiddle ,或展开下面的示例...
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
Array.prototype.forEach.call(elementsToShow, function (element) {
if (isLoaded(element) && isElementInViewport(element)) {
element.classList.add('is-visible');
} else {
element.classList.remove('is-visible');
}
});
});
[...elementsToShow].forEach((imgEl, i) => {
if (
imgEl.src &&
imgEl.getBoundingClientRect().height
) {
imgEl.dataset.isLoaded = true;
console.log(`Img ${i} already loaded`);
} else {
console.log(`Img ${i} still loading... or should be lazyloaded`);
imgEl.onload = function(e) {
console.log(`Img ${i} finally loaded! onload event`);
e.target.dataset.isLoaded = true;
};
if (imgEl.dataset.src) {
console.log(`Img ${i} start lazy load...`);
imgEl.src = imgEl.dataset.src;
}
}
})
function isLoaded(el) {
return el.dataset.isLoaded
}
var elementsToShow = document.querySelectorAll('.show-on-scroll');
$(window).scroll(function() {
Array.prototype.forEach.call(elementsToShow, function(element) {
if (isLoaded(element) && isElementInViewport(element)) {
element.classList.add('is-visible');
} else {
element.classList.remove('is-visible');
}
});
});
[...elementsToShow].forEach((imgEl, i) => {
if (
imgEl.src &&
imgEl.getBoundingClientRect().height
) {
imgEl.dataset.isLoaded = true;
console.log(`Img ${i} already loaded`);
} else {
console.log(`Img ${i} still loading... or should be lazyloaded`);
imgEl.onload = function(e) {
console.log(`Img ${i} finally loaded! onload event`);
e.target.dataset.isLoaded = true;
};
if (imgEl.dataset.src) {
console.log(`Img ${i} start lazy load...`);
imgEl.src = imgEl.dataset.src;
}
}
});
function isLoaded(el) {
return el.dataset.isLoaded
}
// Helper function from: http://stackoverflow.com/a/7557433/274826
function isElementInViewport(el) {
// special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
(rect.top <= 0 &&
rect.bottom >= 0) ||
(rect.bottom >= (window.innerHeight || document.documentElement.clientHeight) &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight)) ||
(rect.top >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight))
);
}
.balltest {
width: 50px;
}
.fade-in {
opacity: 0;
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.standard-push {
opacity: 0;
transform: translateY(4em);
-webkit-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out, translateZ(0);
-moz-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
-o-transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 1s 0.25s ease-out;
transition: transform 4s 0.25s cubic-bezier(0, 1, 0.3, 1), opacity 0.3s 0.25s ease-out;
will-change: transform, opacity;
}
.is-visible {
transform: translateY(0);
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<p style='margin-top: 100vh;'>above</p>
<img class='balltest show-on-scroll standard-push' src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll fade-in' src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll standard-push' data-src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<img class='balltest show-on-scroll fade-in' data-src='http://www.pngall.com/wp-content/uploads/5/Sports-Ball-Transparent.png' />
<p style='margin-bottom: 100vh'>below</p>
</html>
C. 等待
load
文件事件您可以将您的 JS 初始化代码包装成
load
整个文档的事件。在所有资源(CSS、IMG、..)完全加载后触发该事件。window.addEventListener('load', (event) => {
// JS init code hier (images are loaded at this point!)
});
关于javascript - 移动 chrome 上的动画滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68385134/