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

6

34

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>
        );
    }
Derogatory answered 11/6, 2018 at 16:55 Comment(0)
A
53

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.

Anfractuosity answered 11/6, 2018 at 17:26 Comment(2)
This answer is not actual for fresh version of styled components because that syntax `(y) => keyframes`` is wrongAlkaloid
This worked as a charm for me. That's just Javascript new syntax blended with CSS. But this worked only when I added !important to override the original CSS animation.Dishrag
V
9

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;
`
Valenciavalenciennes answered 11/6, 2018 at 17:20 Comment(0)
Z
3

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;
`;
Zenobiazeolite answered 14/8, 2021 at 14:54 Comment(0)
B
0
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",
}));
Boz answered 21/9, 2022 at 19:16 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Humpy
M
0

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>
))}
Mario answered 5/2, 2023 at 7:57 Comment(0)
C
0

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;
    `};
`
Cerated answered 4/2 at 17:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.