【问题标题】:ReactJS change color of element on scroll and when certain position is reachedReactJS 在滚动和到达某个位置时更改元素的颜色
【发布时间】:2018-07-05 15:27:31
【问题描述】:

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

这是我目前得到的:(见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>
   )
 }
}

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;
}

那么,有什么提示吗?

【问题讨论】:

  • 绑定一个滚动事件,检查想要的元素是否可见,如果可见就调用setState。
  • @learner 如果多个部分同时可见怎么办?那么这个解决方案将无法正常工作。
  • 在这种情况下你想做什么? multiple sections 是什么意思?你想只检查背景色吗?在这种情况下,您可以检查:myDiv.style.backgroundColor.
  • @learner 他想在标题到达具有不同背景颜色的新部分时更改标题中文本的颜色以获得更好的对比度。

标签: javascript css reactjs


【解决方案1】:

试试这个:

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>
     )
   }
}

基本上我们只是使用window.scrollY 来了解用户滚动到了哪里。

【讨论】:

  • 你怎么知道一个部分从 400 开始?这些部分可能具有动态内容,使其高度不同。
  • @trixn 完全正确!嗯,也许我可以以某种方式将部分的高度作为道具传递!?
  • @Steve 看我的回答。只需让这些部分决定何时更改颜色,因为它们在渲染后知道自己的大小。或者,您必须将部分的 ref 传递给它们的父级并在那里进行计算。
【解决方案2】:

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

这是查看所有文件的代码沙盒。它有 body.js 和 styles.css 来帮助显示滚动的变化。下面是 Header 组件及其 css 文件。希望这可以帮助! (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 文件。

// 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;
}

【讨论】:

    【解决方案3】:

    在 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>
     )
     }
    }
    

    【讨论】:

      【解决方案4】:

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

      您的 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>
              );
          }
      }
      

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

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

      【讨论】:

        【解决方案5】:

        我会这样走:

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

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

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

        构造函数:

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

        我将添加逻辑:

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

        【讨论】:

        • 但是 OP 想要改变颜色,当他的固定标题到达某个部分时。所以他需要知道他的部分 div 相对于 header 元素的位置,以检查文本颜色是否需要更改。这仅适用于 refs。
        • 我认为我的回答不完整。顺便说一句,OP正在寻求提示。我给了他一个。 :)
        【解决方案6】:

        试试这个 `import React, { useState } from 'react'; 导入'./Navbar.css';

        const NavBar = () => {

        const [navbar, setNavbar] = useState(false);
        const [TextHome,setTextHome]=useState(false);
        const [TextAbout,setTextAbout]=useState(false);
        const [TextService,setTextService]=useState(false);
        const [TextPortfolio,setTextPortfolio]=useState(false);
        const [TextContact,setTextContact]=useState(false);
        
        
        const changeBackground = () => {
            if (window.scrollY >= 200) {
                console.log(window.scrollY);
                setNavbar(true);
                setTextHome(true);
                 if (window.scrollY >= 600 && window.scrollY <= 920 ) {
                    setTextAbout(true);
                    setTextService(false);
                    setTextPortfolio(false);
                    setTextContact(false);
        
        
        
        
                }
                else if (window.scrollY >=921 && window.scrollY <= 1500 ) {
                    setTextService(true);
                    setTextAbout(false);
                    setTextPortfolio(false);
                    setTextContact(false);
        
        
                }
                else if (window.scrollY >= 1501 && window.scrollY <= 2250) {
                    setTextPortfolio(true);
                    setTextService(false);
                    setTextAbout(false);
                    setTextContact(false);
        
                }
                else if (window.scrollY >= 2251) {
                    setTextContact(true);
                    setTextPortfolio(false);
        
                }
                else {
                    setTextAbout(false);
                    setTextService(false);
                    setTextPortfolio(false);
                    setTextContact(false);
        
        
        
                }
        
            }
        
            else {
                setNavbar(false);
                setTextHome(false);
                // setTextAbout(false);
                // setTextService(false);
                // setTextPortfolio(false);
                // setTextContact(false);
        
        
        
            }
        };
        window.addEventListener('scroll', changeBackground);
        
        
        
        
        return (
            <nav className={navbar ? "navbar active navbar-expand-lg navbar-light fixed-top py-3" : "navbar navbar-expand-lg navbar-light fixed-top py-3"} id="mainNav">
                <div className="container">
                    <Link smooth className="navbar-brand nav-link " to="/#app">Start Bootstrap</Link>
                    <button className="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"><span className="navbar-toggler-icon"></span></button>
                    <div className="collapse navbar-collapse" id="navbarResponsive">
        
                            <ul className="navbar-nav ml-auto my-2 my-lg-0">
                                <li className="nav-item active"><Link smooth className="nav-link" style={{color:TextHome?"orange":"#000"}} to="/#app">Home</Link></li>
                                <li className="nav-item"><Link smooth className="nav-link  " style={{color:TextAbout?"orange":"#000"}}  to="/#about">About</Link></li>
                                <li className="nav-item"><Link smooth className="nav-link  " style={{color:TextService?"orange":"#000"}}  to="/#services">Services</Link></li>
                                <li className="nav-item"><Link smooth className="nav-link  " style={{color:TextPortfolio?"orange":"#000"}} to="/#portfolio">Portfolio</Link></li>
                                <li className="nav-item"><Link smooth className="nav-link  " style={{color:TextContact?"orange":"#000"}}  to="/#contact">Contact</Link></li>
                        </ul>
                    </div>
                </div>
            </nav>
        );
        

        } 导出默认导航栏;`

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-09-16
          • 1970-01-01
          • 2014-06-28
          • 1970-01-01
          • 2017-06-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多