我正在利用 Intersection Observer API 在网站标题徽标未位于(或接近位于)背景图像上方时隐藏网站标题徽标。
在 Google Chrome、其他 chromium 浏览器和 Safari(至少是移动版本)上运行良好,但 CSS 动画在 Firefox 上播放非常缓慢,有时会延迟。事实上,有时它甚至不会触发,只是冻结。
当 CSS 动画不是由 Intersection Observer 添加类触发时,它可以正常显示。 (即:下例中的蓝色框默认具有淡入类,当您刷新页面并淡入时,动画可以流畅播放。)
我使用的是 Firefox 132.0.1(64 位)。 我已经要求其他人测试该网站,结果都是一样的。
这是我复制问题的示例页面,使用蓝色正方形作为标题徽标,红色矩形作为背景图像区域:
const header = document.getElementById("headerhide");
const region = document.querySelector(".header-background");
const observer = new IntersectionObserver(([entry]) => {
header.classList.toggle("fade-out", !entry.isIntersecting);
header.classList.toggle("fade-in", entry.isIntersecting);
}, {
threshold: 0.2,
})
observer.observe(region)
.header-background {
height: 500px;
background-color: red;
}
.logo-container {
position: fixed;
top: 2%;
left: 50%;
transform: translate(-50%, 0);
width: 80px;
height: 80px;
background-color: blue;
}
.logo.logo-container {
position: absolute;
}
.container {
height: 2000px;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.fade-in {
opacity: 0;
animation-name: fade-in;
animation-duration: 0.4s;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
}
.fade-out {
opacity: 1;
animation-name: fade-out;
animation-duration: 0.2s;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
}
<div class="container">
<div class="headerhide" id="headerhide">
<div class="logo-container">
<div class="logo"></div>
</div>
</div>
<div class="header-background" id="region"></div>
</div>
(编辑:也在 JSFiddle 上:https://jsfiddle.net/ob2t6wn3/3/)
(CSS 和 js 通常位于不同的文件中,但为了示例,我将它们全部放在 html 中)
我的规格(尽管我在不同的设备上进行了测试,但问题仍然存在。)
操作系统:Windows 11 Home [64位] CPU:Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz 显卡:NVIDIA GeForce RTX 2070 内存:16GB 主板:微星国际有限公司MS-
我尝试过的事情:
检查是否是 Firefox 设置问题,我排除了 about:config 和 Firefox Sync 中的privacy.fingerprintingProtection 标志,因为禁用其中一个或两个都无法解决问题。我想不出任何其他设置可能导致此问题。
将
will-change: opacity;
添加到 CSS 类中,不起作用。
添加了轻微的变换动画来触发硬件加速但不起作用,添加
translateZ(0)
也不起作用。
在 JavaScript 函数中添加 debounce 不起作用 (虽然我不完全确定我是否做对了,但我 3 天前就开始学习 JavaScript 了。)
使用 2 个观察者来切换不同的类,不起作用。
尝试全新安装 Firefox(开发者版)。
我尝试使用 CSS 过渡而不是关键帧,但这也没有解决问题。
我已经设法使用下面的代码使其在我这边工作。
我删除了定位值(
top
、position: fixed
等)并将它们应用到正在观察的元素 - #headerhide
。
我无法给你一个关于为什么它有效的彻底解释,但我假设它要么是因为
#headerhide
之前作为高度为 0 的空容器,因为它唯一的子元素有 position: fixed
,或者因为动画现在直接在可见元素上运行。
但以上只是猜测。
const header = document.getElementById("headerhide");
const region = document.querySelector(".header-background");
const observer = new IntersectionObserver(([entry]) => {
header.classList.toggle("fade-out", !entry.isIntersecting);
header.classList.toggle("fade-in", entry.isIntersecting);
}, {
threshold: 0.2,
})
observer.observe(region)
.header-background {
height: 500px;
background-color: red;
}
#headerhide {
width: 80px;
height: 80px;
z-index: 100;
top: 2%;
left: 50%;
transform: translate(-50%, 0);
position: fixed;
}
.logo-container {
background-color: blue;
height: 100%;
width: 100%;
}
.logo.logo-container {
position: absolute;
}
.container {
height: 2000px;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.fade-in {
opacity: 0;
animation-name: fade-in;
animation-duration: 0.4s;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
}
.fade-out {
opacity: 1;
animation-name: fade-out;
animation-duration: 0.2s;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
}
<div class="container">
<div class="headerhide" id="headerhide">
<div class="logo-container">
<div class="logo"></div>
</div>
</div>
<div class="header-background" id="region"></div>
</div>