LoneCuriousWolf
LoneCuriousWolf

Reputation: 660

How to pass props to keyframes in styled-component with react?

I have following code and I want to pass value of y from react component to moveVertically keyframe. Is it possible to do so ?

import React from 'react';
    import styled, {keyframes} from 'styled-components';


    const moveVertically = keyframes`
        0% {
            transform : translateY(0px) 
        }
        100% {
            transform : translateY(-1000px) //I need y here
        }
    `;

    //I can access y in here via props but can't send it above
    const BallAnimation = styled.g`
        animation : ${moveVertically} ${props => props.time}s linear
    `;


    export default function CannonBall(props) {

        const cannonBallStyle = {
            fill: '#777',
            stroke: '#444',
            strokeWidth: '2px',
        };

        return (
            <BallAnimation time = {4} y = {-1000}>
                <circle cx = {0} cy = {0} r="25" style = {cannonBallStyle}/>
            </BallAnimation>
        );
    }

Upvotes: 34

Views: 26384

Answers (7)

Jthorpe
Jthorpe

Reputation: 10204

I like the CSS Variables approach:

const moveVertically = keyframes`
0% {
    transform : translateY(0px) ;
}
100% {
    transform : translateY(var(--vertical-motion));
}
`;

const BallAnimation = styled.g`
    animation : ${moveVertically} 1s linear;
`;

const MyComponent = () => {
  const ref = useRef<SVGGElement>()
  ref.current?.style.setProperty('--vertical-motion', "-1000px")
  return <BallAnimation ref={ref} />
}

Upvotes: 0

Beno&#238;t Vicente
Beno&#238;t Vicente

Reputation: 1

It worked for me with use of css styled-components library:

const animation = (props) => keyframes`
 0% {
  top: ${props.$position1.top}vh;
  left: ${props.$position1.left}vw;
}
100% {
  top: ${props.$position2.top}vh;
  left: ${props.$position2.left}vw;
}`

const MobileImage = styled.img`
  position: absolute;
  width: ${(props) => props.$cartdWidth}vw;
  height: ${(props) => props.$cartdHeight}vh;
  z-index: ${(props) => props.$zIndex};
  top: ${(props) => props.$position1.top}vh;
  left: ${(props) => props.$position1.left}vw;
  animation: ${(props) =>
    css`
      ${animation(props)} ${flightTime}ms linear forwards;
    `};
`

Upvotes: 0

atazmin
atazmin

Reputation: 5707

This seem to work for me

Inside sx prop

{Array.from(new Array(5)).map((item, index) => (
    <Box
      sx={{
        key={index}
          sx={{
            position: "absolute",
            top: "100%",
            left: "-50%",
            animationName: "move",
            animationTimingFunction: "linear",
            animationIterationCount: "infinite",
            animationDuration: `${index * 6}s`,
            animationDelay: `${index * 6}s`,
            transform: `translateX(${1000 * index}%) `,
            transformOrigin: "left bottom", 
            "@keyframes move": {
             "0%": {
               opacity: 0,
            },
            "50%": {
              opacity: 1,
            },
            "100%": {
              opacity: 0,
            },
        },          
      }}
    >
     Content
    </Box>
))}

Upvotes: 0

RobinPalmier
RobinPalmier

Reputation: 1

const Stick = styled("div")(() => ({
  "@keyframes gradient": {
    "0%": {
      backgroundPosition: "0% 50%",
    },
    "50%": {
      backgroundPosition: "100% 50%",
    },
    "100%": {
      backgroundPosition: "0% 50%",
    },
  },
  width: "40vw",
  height: "20vw",
  background:
    "linear-gradient(-45deg, #ee7752, #e73c7e, #9581F4, #23a6d5, #23d5ab)",
  animation: "gradient 10s ease infinite",
}));

Upvotes: 0

Mohammed Al-Reai
Mohammed Al-Reai

Reputation: 2816

this example for animation for the progress bar for using typescript

    export const animatedProgress = (y:number) => keyframes`
0%{
      width: 0%;
    }
    25%{
        width:  ${y >= 25 ? 25 : y}%;
    }
    50%{
      width:  ${y >= 50 ? 50 : y}%;
    }
    75%{
      width:  ${y >= 75 ? 75 : y}%;
    }
    100%{
      width:  ${y >= 100 ? 100 : y}%;
    }

`;

export const ProgressAnimated = styled("div")<progressAnimated>`

animation : ${props => animatedProgress(props.value)} 3s linear;
`;

Upvotes: 3

Hriday Modi
Hriday Modi

Reputation: 2081

You can make moveVertically a function. Please consider code below:

const moveVertically = (y) => keyframes`
    0% {
        transform : translateY(0px) 
    }
    100% {
        transform : translateY(${y}px)
    }
`;

const BallAnimation = styled.g`
    animation : ${props => moveVertically(props.y)} ${props => props.time}s linear
`;

Here you have y in props of BallAnimation. So you can extract it and pass it to moveVertically function which accepts y value as a parameter.

Upvotes: 53

Steve Holgado
Steve Holgado

Reputation: 12089

How about making moveVertically a function that returns the keyframes styled component?

That way, you can pass in the prop you want:

const moveVertically = (y) =>
  keyframes`
    0% {
      transform: translateY(0px);
    }
    100% {
      transform: translateY(${y}px);
    }
  `

const BallAnimation = styled.g`
  animation: ${props => moveVertically(props.y)} ${props => props.time}s linear;
`

Upvotes: 9

Related Questions