出现的问题
scroll-behavior: smooth 在 iOS 和鸿蒙系统中的某些情况下,确实可能导致滚动动画与 JavaScript 动画的帧数不一致,甚至暂停。这个问题主要是因为 scroll-behavior: smooth 的平滑滚动效果是由浏览器原生的滚动机制驱动的,而 JavaScript 动画(尤其是使用 requestAnimationFrame)可能会与浏览器的滚动渲染产生冲突。
解决方案
1. 禁用 scroll-behavior 在特定设备上的使用
如果你的目标是让平滑滚动在 iOS 和鸿蒙设备上不影响动画效果,可以使用 JavaScript 来检测用户的设备,并有选择性地禁用平滑滚动。
js
复制编辑
if (/iPhone|iPad|iPod|Android|HarmonyOS/i.test(navigator.userAgent)) {
document.documentElement.style.scrollBehavior = 'auto';
} else {
document.documentElement.style.scrollBehavior = 'smooth';
}
这个方法通过检测用户的设备来决定是否应用平滑滚动。
2. 使用 JavaScript 来实现平滑滚动
如果你想完全控制滚动效果,可以自己实现平滑滚动,而不依赖 CSS 的 scroll-behavior。这样就可以避免与 JavaScript 动画的冲突。可以使用 window.scrollTo 或 window.scroll 配合 requestAnimationFrame 来实现自定义平滑滚动效果。
例如,使用 requestAnimationFrame 实现自定义的平滑滚动:
js
复制编辑
function smoothScrollTo(targetY, duration = 500) {
const startY = window.scrollY;
const distance = targetY - startY;
let startTime = null;
function scrollStep(timestamp) {
if (!startTime) startTime = timestamp;
const progress = (timestamp - startTime) / duration;
const scrollY = startY + distance * Math.min(progress, 1);
window.scrollTo(0, scrollY);
if (progress < 1) {
requestAnimationFrame(scrollStep);
}
}
requestAnimationFrame(scrollStep);
}
document.querySelector('#myLink').addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector('#targetSection');
smoothScrollTo(target.offsetTop);
});
这种方法给了你更大的控制权,同时可以避免 scroll-behavior 导致的帧数问题。
3. 优化帧数
在某些情况下,scroll-behavior 可能会导致与动画或渲染循环之间的竞争,尤其是在性能较低的设备上。可以通过减少滚动区域的元素数量、优化动画的帧数或使用 CSS 动画代替 JavaScript 动画来提高性能