我已将 CSS 动画添加到我的 html 页面上的各种 div 元素。但是所有动画同时播放且我看不到页面底部的动画。如何在向下滚动页面时让它们播放?
CSS3-Animate 元素(如果在视口中可见)(页面滚动)
IT技术
javascript
jquery
html
css
animation
2021-03-07 13:39:34
3个回答
使用 IntersectionObserver API
所述IntersectionObserver API提供了一种异步观察目标元素的交点的变化与一个祖先元素或具有顶级文档的视口。
这是一个当 Element 在视口中时触发classList 切换的示例:
const inViewport = (entries, observer) => {
entries.forEach(entry => {
entry.target.classList.toggle("is-inViewport", entry.isIntersecting);
});
};
const Obs = new IntersectionObserver(inViewport);
const obsOptions = {}; //See: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options
// Attach observer to every [data-inviewport] element:
const ELs_inViewport = document.querySelectorAll('[data-inviewport]');
ELs_inViewport.forEach(EL => {
Obs.observe(EL, obsOptions);
});
[data-inviewport] { /* THIS DEMO ONLY */
width:100px; height:100px; background:#0bf; margin: 150vh 0;
}
/* inViewport */
[data-inviewport="scale-in"] {
transition: 2s;
transform: scale(0.1);
}
[data-inviewport="scale-in"].is-inViewport {
transform: scale(1);
}
[data-inviewport="fade-rotate"] {
transition: 2s;
opacity: 0;
}
[data-inviewport="fade-rotate"].is-inViewport {
transform: rotate(180deg);
opacity: 1;
}
Scroll down...
<div data-inviewport="scale-in"></div>
<div data-inviewport="fade-rotate"></div>
观察者选项
要定义另一个父引用元素,请使用rootObservable 选项对象中的选项。根据您的喜好,还有rootMargin超级有用的threshold选项
const obsOptions = {
// Default is null (Browser viewport). Set a specific parent element:
root: document.querySelector('#someSpecificParent'),
// add 40px inner "margin" area at which the observer starts to calculate:
rootMargin: '40px',
// Default is 0.0 meaning the callback is called as soon 1 pixel is inside the viewport.
// Set to 1.0 to trigger a callback when 100% of the target element is inside the viewport,
// or i.e: 0.5 when half of the target element is visible:
threshold: 0.5,
};
查看另一个使用 IntersectionObserver APIthreshold选项的有趣用例。
补充阅读:
使用本机IntersectionObserver API 是解决此问题的最高效方法。
如果您想了解我们过去如何解决类似需求,请以一个小型自定义插件为例查看此答案。
仍然是 Javascript,但在这个版本中你不需要监听滚动事件。速度和性能比每次检查对象是否在视口中要好得多。
检查这个:https : //developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
使用Intersection Observer,您可以在元素可见时定义回调。
选项:
root: null << 如果您希望它在您的视口(可见区域)内,请设置为 null
threshold: 0.3 << 表示 30% 的可见性。如果设置为 0.3,则在可见度达到至少 30% 时调用一次回调,并且在可见度低于 30% 时调用一次回调。
function callbackFunc(entries, observer)
{
entries.forEach(entry => {
var txt = entry.target.id + " visibility: " + entry.isIntersecting;
document.getElementById('log').appendChild(document.createTextNode(txt));
document.getElementById('log').appendChild(document.createElement("br"));
});
}
let options = {
root: null,
rootMargin: '0px',
threshold: 0.3
};
let observer = new IntersectionObserver(callbackFunc, options);
observer.observe(document.getElementById('firstBlock'));
observer.observe(document.getElementById('secondBlock'));
#firstBlock {
width: 50vw;
height: 80vh;
background: red;
}
#secondBlock {
width: 50vw;
height: 80vh;
background: blue;
}
#log {
width: 200px;
height: 80vh;
position: fixed;
right: 0px;
top: 10px;
overflow: auto;
}
First Block:
<div id='firstBlock'> </div>
<br><br><br>
Second Block:
<div id='secondBlock'> </div>
<div id='log'>Log: </div>
另一种方法是使用滚动事件侦听器
document.addEventListener("DOMContentLoaded", function(event) {
document.addEventListener("scroll", function(event) {
const animatedBoxes = document.getElementsByClassName("animated-box");
const windowOffsetTop = window.innerHeight + window.scrollY;
Array.prototype.forEach.call(animatedBoxes, (animatedBox) => {
const animatedBoxOffsetTop = animatedBox.offsetTop;
if (windowOffsetTop >= animatedBoxOffsetTop) {
addClass(animatedBox, "fade-in");
}
});
});
});
function addClass(element, className) {
const arrayClasses = element.className.split(" ");
if (arrayClasses.indexOf(className) === -1) {
element.className += " " + className;
}
}
.animated-box {
width: 150px;
height: 150px;
margin-top: 100vh;
background: blue;
}
.fade-in {
-webkit-animation: fade-in 1.2s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
animation: fade-in 1.2s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
}
@-webkit-keyframes fade-in {
0% {
-webkit-transform: translateY(50px);
transform: translateY(50px);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
@keyframes fade-in {
0% {
-webkit-transform: translateY(50px);
transform: translateY(50px);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
<div>
Start scrolling down...
<div class="animated-box">
</div>
<div class="animated-box">
</div>
<div class="animated-box">
</div>
<div class="animated-box">
</div>
<div class="animated-box">
</div>
</div>