jscottsmith / react-scroll-parallax

🔮 React hooks and components to create parallax scroll effects for banners, images or any other DOM elements.
https://react-scroll-parallax.damnthat.tv/
MIT License
2.9k stars 158 forks source link

Freeze Element #154

Closed Oriole-Alex closed 2 years ago

Oriole-Alex commented 2 years ago

Support

Hi,

I can't for the life of me work out how to freeze a section for a designated amount of scroll distance. I want to keep a background image locked in place for the first few screens before sliding away - how do I do this?

Sorry if this is explained in the docs but I can't find any information on this functionality many thanks

jscottsmith commented 2 years ago

The easiest way to achieve this would be to use a targetElement to trigger scroll progress. There's an example of this in the storybook:

https://react-scroll-parallax-v3.surge.sh/?path=/story/components-parallax-vertical-scroll--with-defined-target-element

Create an element that is positioned within the window when you want the background to animate.

function Component() {
  const targetRef = useRef();
  const { ref } = useParallax({ speed: 10, targetElement: targetRef.current });
  return (
    <>
      <div ref={ref} className="background" />
      <div ref={targetRef} className="target" />
    </>
  );
}

I'm just realizing that targetElement is not documented so I will work on adding that asap.

Let me know if this helps.

Oriole-Alex commented 2 years ago

thanks for the fast reply!

Apologies, I'm not 100% with you. Could you explain further how this works? I'm unclear on how the background element is referring to another to trigger its delayed movement

jscottsmith commented 2 years ago

By default parallax elements are always animated when they are in view. The progress is illustrated clearly in this example

Since you want the background to stop animating at a point but still remain visible (in the view) you need to position an element (can be hidden) that scrolls into view when you want the background to animate, and scrolls out of view when you want the background to stop animating. Defining a targetElement allows you to use another elements progress instead of its own.

Best to just try it out and adapt for your needs:

https://codesandbox.io/s/react-scroll-parallax-target-element-m635p5?file=/src/App.tsx

Oriole-Alex commented 2 years ago

Ah that explains it perfectly! going to give it a go now

thanks a mil for taking the time to reply :)

jscottsmith commented 2 years ago

No problem. Closing this but reach out if you need more help.

Oriole-Alex commented 2 years ago

hi mate, sorry thought i understood but playing with the examples I'm stumped.

So my understanding is that if I reference the element to a

further down the page at the point which I want the background to start moving, the background should stay locked in its original position until that
comes into the view space and as such starts the background to move.

The example (https://codesandbox.io/s/react-scroll-parallax-target-element-m635p5?file=/src/App.tsx) is confusing me because it says that the box should only animate when the line comes up into view but here it animates immediately before stopping after it completes its parallax movement.

Apologies if I'm just not getting something obvious!

jscottsmith commented 2 years ago

My fault.

The sandbox wasn't working correctly on initial load because the ref is only captured on the first render so the Parallax element was never receiving a targetElement

I updated it to use state, set the target element in state in a use effect, then once that target element is available we can render the parallax element. Refresh the sandbox to see.

Oriole-Alex commented 2 years ago

Haha superb! thanks for updating it! I've got it working in my code now with your after your changes 💪thanks again for all the help!

Oriole-Alex commented 2 years ago

Another question has just come up in this vein - how would I scroll something into view, e.g half way up the screen, then lock it in place for a while, before letting it scroll (or whatever parallax animation) off the screen? The currently ref solution seems to only work for keeping something static and visible from the beginning. thanks

jscottsmith commented 2 years ago

You can use position: sticky on the parallax element to achieve such an effect. It will take the correct positioning of a container and the target element to get animation timing at the right moment but it's possible.

I updated the Code Sandbox to illustrate the sticky effect: https://m635p5.csb.app/

Notice that the sticky-container determines when the element is unstuck from the screen. If you're not familiar with how sticky behaves read up on MDN

Oriole-Alex commented 2 years ago

You have smashed it again! thanks a mil this is superb! Really helps having the example

jscottsmith commented 2 years ago

Glad it helps. This is something I plan to document better and provide examples for in #134