Randall
Randall

Reputation: 2858

ReactJS custom cursor effect:Cursor not working when user scroll

Those days I watch in youtube great video how to create custom cursor CSS and JS.

So I wrote this code in ReactJS and create almost similar custom cursor effect.But there and small bug when user scroll (without move mouse only scroll) my custom cursor not moving.

Codesandbox

Please help how to solve this issue.

state = {
    xMain: 0,
    yMain: 0,
    expand: false
  };
  componentDidUpdate() {
    if (this.state.expand) {
      setTimeout(() => {
        this.setState({ expand: false });
      }, 500);
    }
  }

  handleMouseMove = e => {
    const { pageX, pageY } = e;

    this.setState({
      xMain: pageX,
      yMain: pageY
    });
  };
  expandCursor = () => {
    this.setState({
      expand: true
    });
  };
  render = () => {
    const { xMain, yMain } = this.state;

    return (
      <div
        className="container"
        onClick={this.expandCursor}
        onMouseMove={e => this.handleMouseMove(e)}
      >
        <div
          className={this.state.expand ? "cursor expand" : "cursor"}
          style={{
            left: xMain,
            top: yMain
          }}
        />
      </div>
    );
  };

Upvotes: 0

Views: 1707

Answers (2)

Thilina Koggalage
Thilina Koggalage

Reputation: 1084

You need to handle the scroll event. Try something like this.

componentDidUpdate() {
    if (this.state.expand) {
      setTimeout(_ => {
        this.setState({ expand: false });
      }, 500);
    }

    window.addEventListener('scroll', this.handleScroll);
  }

  handleScroll = e => {
    console.log('x');

    this.setState({
      xMain: e.pageX,
      yMain: e.pageY
    });
  };

Upvotes: 0

AppleJam
AppleJam

Reputation: 1039

I have write this demo.

It has a little delay while scrolling, which is about the performance issue. I haven't come up the way to fix.

Anyway, still hope this helps!

In my opinion, to achieve this needs to consider 2 steps:

  1. Add a scroll event listener

    In your code, to add onScroll in .container will not working, because when you scroll, only body element can detect this event.

    Hence we have two ways available:

    a. Bind vanilla Javascript eventList in lifecycles like this.

    b. Make your element scrollable, and bind onScroll in JSX.

    In my code I tried b method. The key is to create a parent wrapper(position: relative; width: 100%;) for container, and add the style height: 100%; to html, body, #root. I have to say I don't know the real reason why add height: 100%; would make this work. I learn this by react-sprint example.

  2. Get the scroll offset for the event, and calculate the position of cursor.

    Once the onScroll works, the second thing is : how to calculate the cursor position form scroll event?

    I notice that previous wrap approach made the pageX, pageY value changes. The value is not the offset to the document anymore, it's the offset to the viewport. (I guess it only count in the scroll offset with body.)

    And we can use scrollTop value of scroll event to get the scroll offset from the document:

    scrollTop

    The Element.scrollTop property gets or sets the number of pixels that an element's content is scrolled vertically.

    https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop

    Last step, defined the x,y properties for scroll event and mouse event individually, then sum up the scrollX and mouseY as left; sum up the scrollY(the scrolled height) and mouseY (the y offset of mouse from viewport) as top.

Upvotes: 2

Related Questions