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.
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
Finally figure out the solution
The key is to use
controller.scrollTo(scene.triggerPosition() + the_progress_you_want * scene.duration());
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>
);
}