javascript - 在香草JS中滚动动画
问题描述
我知道很容易在滚动上触发触发器并通过 向 HTML 元素添加类名jquery
,但我想知道是否有可能(甚至值得)尝试在 react 或 vanilla 中这样做javascript
。我正在学习反应并希望在用户滚动网页一定距离时触发动画。到目前为止,我还没有使用jquery
过很多人建议您应该尽可能坚持使用 vanilla javascript
,因为它非常强大并且您不需要导入jquery
库。
我已经使用下面的代码成功地在 vanilla JS 中实现了滚动触发器,尽管它的效率非常低,因为它在滚动上使用了事件侦听器(也许Jquery
无论如何都会这样做?)。jquery 只是做我想做的最好的方法吗?在此先感谢各位,这是意大利面条代码:
function getDocHeight(D) {
return Math.max(
D.body.scrollHeight, D.documentElement.scrollHeight,
D.body.offsetHeight, D.documentElement.offsetHeight,
D.body.clientHeight, D.documentElement.clientHeight
)
}
function amountscrolled(){
var winheight= window.innerHeight || (document.documentElement || document.body).clientHeight
var docheight = getDocHeight(document)
var scrollTop = window.pageYOffset || (document.documentElement || document.body.parentNode || document.body).scrollTop
var trackLength = docheight - winheight
var pctScrolled = Math.floor(scrollTop/trackLength * 100) // gets percentage scrolled (ie: 80 or NaN if tracklength == 0)
if (pctScrolled > 50) {
document.getElementById('anim').className+=" animate";
}
}
window.addEventListener("scroll", function(){
amountscrolled()
}, false)
解决方案
这是一个老问题,但唯一现有的答案是完全不相关的,现在有一个很好的方法可以做到这一点IntersectionObserver
——API。
const callback = (entries) =>
entries.forEach(entry =>
entry.isIntersecting && entry.target.classList.add("show")
);
const observer = new IntersectionObserver(callback);
const animate = document.querySelectorAll(".animate");
animate.forEach(div => observer.observe(div));
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
}
body > * + * { margin-top: 1em }
#content {
height: 100vh;
background: red;
}
.animate {
height: 20vh;
background: blue;
opacity: 0;
transition: opacity 1s;
}
.animate.show {opacity: 1}
<div id="content">content</div>
<div class="animate">animate me 1</div>
<div class="animate">animate me 2</div>
<div class="animate">animate me 3</div>
最好的部分是,对于您的 React 需求,甚至还有一个您可以使用的库! 反应交叉观察者
$ npm install react-intersection-observer --save
$ # or
$ yarn add react-intersection-observer
(来自自述文件)
import React from 'react';
import { useInView } from 'react-intersection-observer';
const Component = () => {
const { ref, inView, entry } = useInView({
/* Optional options */
threshold: 0,
});
return (
<div ref={ref}>
<h2>{`Header inside viewport ${inView}.`}</h2>
</div>
);
};
推荐阅读
- android - 如何在 Flutter 中创建类似 Bottomsheet 的 UI
- python - 如何在python中读取文本文件的任意行?
- c - 为什么权限参数会影响我的小测试程序中写入文件的内容?
- json - Spark中Json列的哈希值
- react-native - 为什么 Android Emulator 只显示一个空白页面?
- sockets - 如何在程序集的套接字编程中找到参数的值?
- jquery - 视频标签有课时如何停止播放html 5视频?
- ios - 如何使 iPhone X 上的状态栏变为纯白色?
- java - 如何从json中获取列表列表?
- python - 使用 google 的 ip 而不是域名时的 TooManyRedirects