我有一个 div,里面有两个 span。 span的位置是span1使用从div中心开始的粘性位置,而span2位于div的底部。这个想法是,当用户滚动时,最初不透明度为 0 的 span1 变得可见,进一步滚动后,span2 变得可见。我尝试通过手动调整它们变得可见的点来实现这一点。有没有最佳的方法来实现这一目标?我附上我的代码作为参考
window.addEventListener('scroll', function() {
const message = document.querySelector('.message');
const deathSpan = document.querySelector('.message > span');
const vhDiv = document.querySelector('.vh');
const rect = message.getBoundingClientRect();
const windowHeight = window.innerHeight;
const fadeStart1 = windowHeight * 0.3;
const fadeEnd1 = windowHeight * 0.6;
const fadeStart2 = windowHeight * 0.5;
const fadeEnd2 = windowHeight * 0.9;
if (rect.top <= fadeEnd1 && rect.bottom >= fadeStart1) {
let opacity1 = (fadeEnd1 - rect.top) / (fadeEnd1 - fadeStart1);
opacity1 = Math.min(Math.max(opacity1, 0), 1);
deathSpan.style.opacity = opacity1;
} else {
deathSpan.style.opacity = 0;
}
if (rect.top <= fadeEnd2 && rect.bottom >= fadeStart2) {
let opacity2 = (fadeEnd2 - rect.top) / (fadeEnd2 - fadeStart2);
opacity2 = Math.min(Math.max(opacity2, 0), 1);
vhDiv.style.opacity = opacity2;
} else {
vhDiv.style.opacity = 0;
}
});
.above-divs a{
font-size:10rem;
background-color: black;
color: white;
}
.message {
width: 100%;
height: 150vh;
display: flex;
position: relative;
background-color: rgb(0, 0, 0);
align-items: center;
}
.message span {
font-size: 10vw;
color: rgb(255, 255, 255);
}
.message>span {
position: sticky;
top: 50%;
opacity: 0;
transition: opacity 0.5s ease;
}
.vh {
position: absolute;
bottom: 0;
right: 10%;
opacity: 0;
transition: opacity 0.5s ease;
}
<div class="above-divs">
<a href="">hello</a>
</div>
<div class="message">
<span>Text1 (span1)</span>
<div class="vh">
<span>Text2 (span2)</span>
</div>
</div>
这可能有用:Intersection Observer API MDN
此 API 提供了一种有效的方法来跟踪元素相对于视口的可见性变化。
你可以尝试做类似的事情:
// Target elements
const span1 = document.querySelector('.message > span');
const span2 = document.querySelector('.vh > span');
// Fade-in observer for span1 (centered/sticky)
const observer1 = new IntersectionObserver(function (entries) {
entries.forEach(entry => {
if (entry.intersectionRatio > 0.5) { // If more than half of the span is visible
span1.style.opacity = 1;
} else {
span1.style.opacity = 0;
}
});
}, observerOptions);
// Fade-in observer for span2 (at the bottom)
const observer2 = new IntersectionObserver(function (entries) {
entries.forEach(entry => {
if (entry.intersectionRatio > 0.5) { // Same logic for span2
span2.style.opacity = 1;
} else {
span2.style.opacity = 0;
}
});
}, observerOptions);
// Observe the target elements
observer1.observe(span1);
observer2.observe(span2);
});