javascript ReactJS 在滚动和到达特定位置时更改元素的颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48458832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 08:03:14  来源:igfitidea点击:

ReactJS change color of element on scroll and when certain position is reached

javascriptcssreactjs

提问by ST80

Is it possible to change the class of my header so that it will change its color when the background changes? I have a header and some sections. The header is fixed and when it foreaxmple reaches a section with a different backgroundcolor, I want to change the headers color for better readability, but I don't know how to do that. I've searched the web for it but I couldn't eally find something.

是否可以更改标题的类,以便在背景更改时更改其颜色?我有一个标题和一些部分。标题是固定的,当它到达具有不同背景颜色的部分时,我想更改标题颜色以提高可读性,但我不知道该怎么做。我已经在网上搜索过它,但我找不到任何东西。

this is what I got so far: (see this JSFIDDLE)

这就是我到目前为止所得到的:(见这个JSFIDDLE

class Div extends React.Component{
   constructor() {
     super()

     this.state = {
       headerClass: 'white'
     }
}
changeColor() {
  // something like
     this.setState({ headerClass: 'black'})
}
render(){
  return(
    <div>
      <div id="header">
        <h1 className={`${this.state.headerClass}`}>
          This is the header
        </h1>
     </div>      
     <div id="section_1" className="section">
        This is section 1
     </div>

     <div id="section_2" className="section">
        This is section 2
     </div>

     <div id="section_3" className="section">
        This is section 3
     </div>

     <div id="section_4" className="section">
        This is section 4
     </div>

     <div id="section_5" className="section">
        This is section 5
     </div>

   </div>
   )
 }
}

the CSS:

CSS:

#main {
 height: 2000px;
 position: relative;
}

#section_1 {
  background: grey;
}

.section {
  height: 400px;
  background: white;
  padding: 30px 0;
}

#header {
  height: 50px;
  background: transparent;
  position: fixed;
  width: 100%;
  left: 0;
  top: 0;
  right: 0;
  z-index: 1
}

h1 {
 color: white;
}

So, are there any hints?

那么,有什么提示吗?

回答by Liren Yeo

Try this:

试试这个:

import React from 'react'

export default class Div extends React.Component{
  state = {
    color: 'white'
  }

  listenScrollEvent = e => {
    if (window.scrollY > 400) {
      this.setState({color: 'black'})
    } else {
      this.setState({color: 'white'})
    }
  }

  componentDidMount() {
    window.addEventListener('scroll', this.listenScrollEvent)
  }

  render() {
    return(
      <div>
        <div id="header">
          <h1 style={{color: this.state.color}}>
            This is the header
          </h1>
       </div>
       <div id="section_1" className="section">
          This is section 1
       </div>

       <div id="section_2" className="section">
          This is section 2
       </div>

       <div id="section_3" className="section">
          This is section 3
       </div>

       <div id="section_4" className="section">
          This is section 4
       </div>

       <div id="section_5" className="section">
          This is section 5
       </div>

     </div>
     )
   }
}

Basically we just use window.scrollYto know where has the user scrolled to.

基本上我们只是window.scrollY用来知道用户滚动到哪里。

回答by trixn

You could make your sections own components that keep a reference to their DOM element. Your Section component could then listen to a scroll event and invoke a callback that it has been given by the parent container when the top of your components DOM element reaches your fixed header.

您可以让您的部分拥有保留对其 DOM 元素的引用的组件。然后,当您的组件 DOM 元素的顶部到达您的固定标题时,您的 Section 组件可以侦听滚动事件并调用父容器提供的回调。

Your Section component could look something like this.

您的 Section 组件可能看起来像这样。

class Section extends React.Component {

    ref = node => {
        this.ref = node;
        window.addEventListener('scroll', this.onScroll);
    }

    componentWillUnmount() {
        window.removeEventListener('scroll', this.onScroll);
    }

    onScroll = event => {
        const {changeHeaderColor} = this.props;
        // calculate if the top value is inside your header by using the ref
        if (...) {
            changeHeaderColor();
        }
    }

    render() {
        const {id, children} = this.props;

        return (
            <div id={id} className="section" ref={this.ref}>{children}</div>
        );
    }
}

Then you could render your sections like this:

然后你可以像这样渲染你的部分:

<Section id="section-1" changeHeaderColor={this.changeColor}> content here </Section>

回答by Yohan

You could do this with React Hooks. This is what I did below.

你可以用 React Hooks 做到这一点。这就是我在下面所做的。

Here is a Code SandBox to help. (https://codesandbox.io/s/header-change-color-onscrolly-2z3vt)

这里有一个代码沙盒可以提供帮助。(https://codesandbox.io/s/header-change-color-onscrolly-2z3vt

// Header Component

import React, { useState, useEffect } from 'react'

import "./Header.css"

function Header2() {
const [header, setHeader] = useState("header")

const listenScrollEvent = (event) => {
  if (window.scrollY < 73) {
    return setHeader("header")
  } else if (window.scrollY > 70) {
    return setHeader("header2")
  } 
}

useEffect(() => {
  window.addEventListener('scroll', listenScrollEvent);

  return () =>
    window.removeEventListener('scroll', listenScrollEvent);
}, []);

  return (
    <header className={header}>
      <div className="logo">Logo</div>
      <ul className="links">
        <li className="link-item">home</li>
        <li className="link-item">about</li>
        <li className="link-item">join</li>
      </ul>
    </header>
  );
}

export default Header2;

css file.

css 文件。

// Styles header.css

.header {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 120px;
  background-color: #fff;
  color: #333;
  transform: translateY(0);
  transition: transform 0.6s ease;
}

.header2 {
  position: fixed;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 86px;
  background-color: gray;
  color: rosybrown;
  transform: translateY(10);
  transition: transform 6s ease;
  animation: myanimation 3s;
}
@keyframes myanimation {
  0% {
    background-color: transparent;
    color: transparent;
  }
  35% {
    background-color: gray;
    color: rosybrown;
  }
  100% {
    background-color: gray;
    color: rosybrown;
  }
}

.logo {
  margin: 0 24px;
  font-size: 28px;
  color: #f59596;
}

.links {
  padding: 0;
  margin: 0 24px;
}

.link-item {
  display: inline-block;
  margin: 0 12px;
  cursor: pointer;
}

回答by Devyn

The answer using hooks in React 16

在 React 16 中使用钩子的答案

import React from 'react'

export default Div => (){
  const [headerColor, setHeaderColor] = useState("white")


const listenScrollEvent = () => {
    window.scrollY > 10
      ? setHeaderColor("black")
      : setHeaderColor("white")
  }
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
  window.addEventListener("scroll", listenScrollEvent)
})

render() {

return(
  <div>
    <div id="header">
      <h1 style={{color: headerColor}}>
        This is the header
      </h1>
   </div>
   <div id="section_1" className="section">
      This is section 1
   </div>

   <div id="section_2" className="section">
      This is section 2
   </div>

   <div id="section_3" className="section">
      This is section 3
   </div>

   <div id="section_4" className="section">
      This is section 4
   </div>

   <div id="section_5" className="section">
      This is section 5
   </div>

 </div>
 )
 }
}

回答by learner

This is how I would go:

这就是我要去的方式:

I will bind a function on scroll in componentDidMount:

我将在 componentDidMount 中绑定一个滚动函数:

window.addEventListener("scroll", this.boundFun, false);

I will defined the function and add reference in constructor:

我将定义函数并在构造函数中添加引用:

constructor:

构造函数:

    this.boundFun = this.scrollListingFun.bind(this);

I will add logic in:

我将添加逻辑:

scrollListingFun() {
  //  add logic for checks here.
}