Search code examples
javascriptcssreactjsscrollmagic

How to update progress


When you scroll down the page, you will see the element with #pin will be sticky and the currentPercentage will keep updating until the value of currentPercentage is 1 and then not sticky anymore.

enter image description here

The problem is after I scroll to some value, I click the update progress to 0.5. The value of currentPercentage will become 0.5, but if I then scroll. The value will jump to previous value.

For example, if I scroll and stop at 0.33 and then click the button, the value of currentPercentage will become 0.5.
If I scroll down now, the value will increase from 0.33 instead of 0.5, which is mainly the problem.

How to fix it?

App.js

import "./styles.css";
import ScrollMagic from "scrollmagic";
import React, { useState, useEffect } from "react";

export default function App() {
  const [currentPercentage, setCurrentPercentage] = useState(0);

  const scrollController = new ScrollMagic.Controller({
    globalSceneOptions: { triggerHook: "onLeave" }
  });
  useEffect(() => {
    new ScrollMagic.Scene({
      triggerElement: "#pin",
      duration: 1000,
      offset: -10
    })
      .setPin("#pin")
      .setClassToggle("#pin", "green")
      .on("progress", function (e) {
        console.log(e.progress);
        let progress = e.progress;
        setCurrentPercentage(progress);
      })
      .addTo(scrollController);
  }, []);

  const updateProgress = () => {
    setCurrentPercentage(0.5);
  };

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>{" "}
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <div id="pin">
        <div>{currentPercentage}</div>
        <button
          onClick={() => {
            updateProgress();
          }}
        >
          Update Progress to 0.5
        </button>
      </div>
      <div
        style={{ margin: "1rem", border: "1px solid grey", height: "500px" }}
      />
    </div>
  );
}

Codesandbox
https://codesandbox.io/s/flamboyant-aryabhata-oi5xr?file=/src/App.js


Solution

  • Finally figure out the solution

    The key is to use

     controller.scrollTo(scene.triggerPosition() + the_progress_you_want * scene.duration());
    

    In `updateProgress` function.
    Also, you have to initial `scene` and `controller` in React.state ``` const [controller, setController] = useState(null); const [scene, setScene] = useState(null); ```

    The complete solution is

    import "./styles.css";
    import ScrollMagic from "scrollmagic";
    import React, { useState, useEffect } from "react";
    
    export default function App() {
      const [currentPercentage, setCurrentPercentage] = useState(0);
    
      const [controller, setController] = useState(null);
      const [scene, setScene] = useState(null);
    
      useEffect(() => {
        const scrollController = new ScrollMagic.Controller({
          globalSceneOptions: { triggerHook: "onLeave" }
        });
        const scrollScene = new ScrollMagic.Scene({
          triggerElement: "#pin",
          duration: 1000,
          offset: -10
        })
          .setPin("#pin")
          .setClassToggle("#pin", "green")
          .on("progress", function (e) {
            let progress = e.progress;
            setCurrentPercentage(progress);
          });
        scrollScene.addTo(scrollController);
        setController(scrollController);
        setScene(scrollScene);
      }, []);
    
      const updateProgress = () => {
        controller.scrollTo(scene.triggerPosition() + 0.5 * scene.duration());
        setCurrentPercentage(0.5);
      };
    
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>{" "}
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
          <div id="pin">
            <div>{currentPercentage}</div>
            <button
              onClick={() => {
                updateProgress();
              }}
            >
              Update Progress to 0.5
            </button>
          </div>
          <div
            style={{ margin: "1rem", border: "1px solid grey", height: "500px" }}
          />
        </div>
      );
    }