首页 > 解决方案 > 在香草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)

标签: javascriptjqueryhtmlreactjs

解决方案


这是一个老问题,但唯一现有的答案是完全不相关的,现在有一个很好的方法可以做到这一点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>
  );
};

推荐阅读