Search code examples
cssreactjsreact-hooksstyled-components

How to send data from styled component to a function?


I am trying to make a scrolling animation something like this using styled components and react. My strategy is to reduce the value of transform: scale(1) so that as the user scrolls down the image width and height will be reduced and similar effect will be obtained. To do that I need to access that property and use it in a function and then use it in an useEffect hook. I checked the documentation of styled components yet I guess I am missing something. Here is the code:

const AnimationImg = styled.img.attrs((props) => ({ src: props.src }))`
  position: absolute;
  top: 0;
  object-fit: cover;
  transform: scale(1);
  transform-origin: 49% 50%;
`;
const Animation = () => {
  //Scroll positionu yakalamami sagliyor.
  const [scrollPosition, setScrollPosition] = useState(0);
  const [zoom, setZoom] = useState(1);

  const handleScroll = () => {
    const position = window.pageYOffset;
    setScrollPosition(position);
  };

  const handleZoom = () => {
    if (scrollPosition >= 2000 && handleScroll) {
      // function here
    }
  };

zoom logic:

const handleZoom = () => {
    if (scrollPosition >= 2000 && handleScroll) {
      setZoom(zoom - 0.001);
    }
  };

Solution

  • Since zoom is derived from the scrollPosition state, you can recompute it whenever the component renders, and pass it as a prop to the styled component. Use interpolation inside scale to use the zoom.

    const AnimationImg = styled.img`
      position: absolute;
      top: 0;
      object-fit: cover;
      transform: scale(${({ zoom }) => zoom});
      transform-origin: 49% 50%;
    `;
    
    const Animation = () => {
      const [scrollPosition, setScrollPosition] = useState(0);
      
      const zoom = scrollPosition >= 2000 ? zoomFunction(scrollPosition) : 1;
      
      useEffect(() => {
        const handleScroll = () => {
          setScrollPosition(window.pageYOffset);
        };
        
        window.addEventListener('scroll', handleScroll);
    
        return () => {
          window.removeEventListener('scroll', handleScroll);
        };
      }, []);
      
      return (
        <AnimationImg zoom={zoom} />
      );
    }