This is the 23rd day of my participation in Gwen Challenge

preface

The hover button made yesterday is not satisfactory, not bad, but does not meet the demand. What the programmer has to do is meet the requirements. It has to be a do-over.

The new requirement is that the hover button is fixed on the upper right side of the window. When the window is rolling, the button is hidden on the right side of the window and part of it is exposed, which does not affect the user’s view. If the scroll is not displayed, the button is easy for users to click.

Demand analysis

This requirement is mainly to achieve two things:

  1. Listen for page scrolling
  2. Hide and show buttons

implementation

1. Page listening

I originally thought of the window.addeventlinstener method to listen for page scrolling, but since most mobile layouts are different, it may not be window, or some other component’s scrolling. A page like our own, window.addeventlinstener, can’t listen to the scrolling of the list.

So first find the node or parent node of the list to listen. The listening method is generally bound after the node is mounted, and the method is roughly as follows:

componentDidMount() {
    this.scrollDOM.addEventListener("scroll".this.onScroll, {
      passive: false}); } onScroll =(event) = > {
    // If there is no scrolling, the setting is scrolling
    if (!this.state.scrolling) {
      this.setState({ scrolling: true}); }};Copy the code

Set the listener method, of course, also remember to cancel the listener method:

componentWillUnmount() {
    this.scrollDOM.removeEventListener("scroll".this.onScroll);
}
Copy the code

Because the scrolling event is triggered frequently, it is best not to change it all the time to ensure performancescrollingThe value of the

So, I added a timer that, like the idea of stabilization, only assigns values if they are not triggered for 1s.

if (this.timer) {
    clearTimeout(this.timer);
    this.timer = null;
}
this.timer = setTimeout(() = > {
    this.setState({ scrolling: false });
    clearTimeout(this.timer);
    this.timer = null;
}, 1000);
Copy the code

2. The button is hidden and displayed

This part is relatively simple and can be controlled with CSS. I used fixed and Transform to change the position of the button.

.float-button {
  position: fixed;
  top: 388px;
  right: 0;
  width: 58px;
  height: 58px;
  transition-duration: 0.4 s;
}

.float-button.float-button__scrolling {
  transform: translateX(55%);
}
Copy the code

The assignment of className is determined by state.

className = `button float-button The ${this.state.scrolling ? "float-button__scrolling" : ""
}`;
Copy the code

code

The full code is as follows:

import React, { Component } from "react";

class FloatButton extends Component {
  constructor(props) {
    super(props);

    this.state = {
      scrolling: false};this.scrollDOM = window;
    this.timer = null;
  }
  onScroll = (event) = > {
    if (!this.state.scrolling) {
      this.setState({ scrolling: true });
    }
    if (this.timer) {
      clearTimeout(this.timer);
      this.timer = null;
    }
    this.timer = setTimeout(() = > {
      this.setState({ scrolling: false });
      clearTimeout(this.timer);
      this.timer = null;
    }, 1000);
  };
  componentDidMount() {
    if (this.props.scrollDOM) {
      this.scrollDOM = this.props.scrollDOM;
    }
    this.scrollDOM.addEventListener("scroll".this.onScroll, {
      passive: false}); }componentWillUnmount() {
    this.scrollDOM.removeEventListener("scroll".this.onScroll);
    this.timer = null;
  }
  render() {
    const { img } = this.props;
    return <a {. this.getProps()} >{img && <img src={img} alt="" />}</a>;
  }
  getProps() {
    let props = Object.assign({}, this.props);
    props.className = `button float-button The ${this.state.scrolling ? "float-button__scrolling" : ""
    }`;
    returnprops; }}export default FloatButton;
Copy the code

The full effect is as follows: