页面滚动时导航渐变

最近在开发移动端H5页面时,遇到渐变导航的需求点,想了两种方案,在此记录下~

总的来说,渐变导航分为两种(仅仅在我看来哈),一种是 渐变进度可人为控制,另一种是渐变进度不可控。

可人为控制 的意思是:你可以按住屏幕慢慢滚动并在此过程中任意停留,在任意停留点中你可以看到当前渐变程度和效果,并且在你停留的这个点,渐变效果不会发生改变,当再次滚动时渐变程度才会有所变化。它的原理就是:通过监听页面滚动的 scrollTop 值,在不同的 scrollTop值范围中,给导航的容器元素对应设置不同的 opacity。

不可控 的意思是:当页面滚动到某个值时就触发导航样式变化,就算你停下滚动,他也会自动渐变完整个效果。

它的原理就是:当页面滚动到某个值,就设置新的样式,并且通过transition做过度处理。

可人为控制渐变进度

state = {
    isScroll: false,
    headerOpacity: 1,
  }
componentDidMount() {
    document.documentElement.scrollTop = 0
    document.body.scrollTop = 0
    window.pageYOffset = 0
    const {dispatch} = this.props
    dispatch(getHottestTopList({limit: 50}))
    window.addEventListener('scroll', this.onScroll, getListenerOptions())
  }

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



onScroll = evt => {
    const scrollTop = Math.max(
      window.scrollY,
      document.documentElement.scrollTop
    )
    if (scrollTop >= 40) {
      this.setState({isScroll: true, headerOpacity: 1})
    } else if (scrollTop >= 35) {
      this.setState({isScroll: true, headerOpacity: 0.8})
    } else if (scrollTop >= 30) {
      this.setState({isScroll: true, headerOpacity: 0.6})
    } else if (scrollTop >= 25) {
      this.setState({isScroll: true, headerOpacity: 0.4})
    } else if (scrollTop >= 20) {
      this.setState({isScroll: true, headerOpacity: 0.2})
    } else {
      this.setState({isScroll: false, headerOpacity: 1})
    }
  }

HTML:

<FullscreenHeaderWrap
          className={cx('GroupHottestList__HeaderWrap', {
            'GroupHottestList__HeaderWrap--scroll': isScroll,
          })}
          style={{opacity: headerOpacity}}
        >
          <div className="GroupHottestList__Header">
            <div
              className="GroupHottestList__Header__btnBack"
              role="button"
              tabIndex={0}
              onClick={() => {
                closeWindow()
              }}
            />
            <span className="GroupHottestList__Header__title">社团最燃榜</span>
            <div className="GroupHottestList__Header__iconBtnWrap">
              <div
                className="GroupHottestList__Header__btnRule"
                role="button"
                tabIndex={0}
                onClick={() => {
                  openUrl({
                    url: `${
                      window.location.origin
                    }/hybrid/topic/groupHottestRule`,
                  })
                }}
              >
                榜单规则
              </div>
              <div
                className="GroupHottestList__Header__btnShare"
                role="button"
                tabIndex={0}
                onClick={this.toShare}
              />
            </div>
          </div>
        </FullscreenHeaderWrap>

CSS

&__HeaderWrap {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        background-color: transparent;
        z-index: 1;
        &--scroll {
            background-color: #fff;
            .GroupHottestList__Header__btnBack {
                background: url("./images/back-black.png") no-repeat center center / 100% 100% transparent;
            }
            .GroupHottestList__Header__title {
                color: #242529;
            }
            .GroupHottestList__Header__btnRule {
                background: #FFFFFF;
                color: #999EAD;
                border: 1px solid #F3F3F9;
            }
            .GroupHottestList__Header__btnShare {
                background: url("./images/share-black.png") no-repeat center center / 100% 100% transparent;
            }
        }
    }
    &__Header {
        width: 100%;
        height: 44px;
        padding: 0 16px;
        box-sizing: border-box;
        display: flex;
        align-items: center;
        justify-content: space-between;
        &__btnBack {
            width: 24px;
            height: 24px;
      background: url("./images/back-white.png") no-repeat center center / 100% 100% transparent;
        }
        &__title {
            font-style: normal;
            font-weight: 500;
            font-size: 18px;
            line-height: 25px;
            color: #FFFFFF;
        }
        &__iconBtnWrap {
            display: flex;
            align-items: center;
            position: relative;
        }
        &__btnRule {
            width: 70px;
            height: 24px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 22px;
            box-sizing: border-box;
            text-align: center;
            line-height: 24px;
            font-style: normal;
            font-weight: normal;
            font-size: 13px;
            color: #FFFFFF;
            position: absolute;
            top: 0;
            left: -82px;
        }
        &__btnShare {
            width: 24px;
      height: 24px;
      background: url("./images/share-white.png") no-repeat center center / 100% 100% transparent;
        }
    }

不可控渐变进度

state = {
    isScroll: false,
}


componentDidMount() {
    document.documentElement.scrollTop = 0
    document.body.scrollTop = 0
    window.pageYOffset = 0
    const {dispatch} = this.props
    dispatch(getHottestTopList({limit: 50}))
    window.addEventListener('scroll', this.onScroll, getListenerOptions())
  }

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


 onScroll = evt => {
    const scrollTop = Math.max(
      window.scrollY,
      document.documentElement.scrollTop
    )
    if (scrollTop >= 25) {
      this.setState({isScroll: true})
    } else {
      this.setState({isScroll: false})
    }
  }

HTML

<FullscreenHeaderWrap
          className={cx('GroupHottestList__HeaderWrap', {
            'GroupHottestList__HeaderWrap--scroll': isScroll,
          })}>
          <div className="GroupHottestList__Header">
            <div
              className="GroupHottestList__Header__btnBack"
              role="button"
              tabIndex={0}
              onClick={() => {
                closeWindow()
              }}
            />
            <span className="GroupHottestList__Header__title">社团最燃榜</span>
            <div className="GroupHottestList__Header__iconBtnWrap">
              <div
                className="GroupHottestList__Header__btnRule"
                role="button"
                tabIndex={0}
                onClick={() => {
                  openUrl({
                    url: `${
                      window.location.origin
                    }/hybrid/topic/groupHottestRule`,
                  })
                }}
              >
                榜单规则
              </div>
              <div
                className="GroupHottestList__Header__btnShare"
                role="button"
                tabIndex={0}
                onClick={this.toShare}
              />
            </div>
          </div>
        </FullscreenHeaderWrap>

CSS

&__HeaderWrap {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        background-color: transparent;
        transition: background-color 0.2s ease-out;
        z-index: 1;
        &--scroll {
            transition: background-color 0.5s ease-in; // 先慢后快
            background-color: #fff;
            .GroupHottestList__Header__btnBack {
                background: url("./images/back-black.png") no-repeat center center / 100% 100% transparent;
            }
            .GroupHottestList__Header__title {
                color: #242529;
            }
            .GroupHottestList__Header__btnRule {
                background: #FFFFFF;
                color: #999EAD;
                border: 1px solid #F3F3F9;
            }
            .GroupHottestList__Header__btnShare {
                background: url("./images/share-black.png") no-repeat center center / 100% 100% transparent;
            }
        }
    }
    &__Header {
        width: 100%;
        height: 44px;
        padding: 0 16px;
        box-sizing: border-box;
        display: flex;
        align-items: center;
        justify-content: space-between;
        &__btnBack {
            width: 24px;
            height: 24px;
      background: url("./images/back-white.png") no-repeat center center / 100% 100% transparent;
        }
        &__title {
            font-style: normal;
            font-weight: 500;
            font-size: 18px;
            line-height: 25px;
            color: #FFFFFF;
        }
        &__iconBtnWrap {
            display: flex;
            align-items: center;
            position: relative;
        }
        &__btnRule {
            width: 70px;
            height: 24px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 22px;
            box-sizing: border-box;
            text-align: center;
            line-height: 24px;
            font-style: normal;
            font-weight: normal;
            font-size: 13px;
            color: #FFFFFF;
            position: absolute;
            top: 0;
            left: -82px;
        }
        &__btnShare {
            width: 24px;
      height: 24px;
      background: url("./images/share-white.png") no-repeat center center / 100% 100% transparent;
        }
    }        
原文地址:https://www.cnblogs.com/chenbeibei520/p/15046405.html