序列帧动画

import React, { useEffect, useMemo, useState } from 'react'
import styled, { keyframes } from 'styled-components'

interface StyledAnimationProps {
  animation: ReturnType<typeof keyframes> | null
}

const SEQUENCE_FRAME_COUNT = 55

const FireworksAnimation = () => {
  const [frameAnimation, setFrameAnimation] = useState<ReturnType<typeof keyframes> | null>(null)
  const [isFramesLoaded, setIsFramesLoaded] = useState(false)

  const loadFrames = async () => {
    try {
      const frameImports = await Promise.all(
        Array.from({ length: SEQUENCE_FRAME_COUNT }, (_, index) =>
          import(`@/assets/images/pk/fireworksAnimation/fireworks${index + 1}.webp`).then(module => module.default)
        )
      )

      const framesCount = SEQUENCE_FRAME_COUNT

      const getURL = (index: number) => frameImports[index].src

      const generatedFrames = Array.from({ length: framesCount }, (_, frameIndex) => {
        const imageURL = getURL(frameIndex)
        if (++frameIndex === framesCount) {
          return `
            100% {
              background-image: url(${imageURL});
              background-size: cover;
            }
          `
        }
        return `
          ${frameIndex * (100 / framesCount)}% {
            background-image: url(${imageURL});
            background-size: cover;
          }
        `
      })

      const animation = keyframes`
        ${generatedFrames.join('')}
      `

      setFrameAnimation(animation)
      setIsFramesLoaded(true)
    } catch (error) {
      console.error('Error loading frames:', error)
    }
  }

  useEffect(() => {
    if (!isFramesLoaded) {
      loadFrames()
    }
  }, [isFramesLoaded])

  const memoizedAnimation = useMemo(() => frameAnimation, [frameAnimation])

  return (
    <StyledFireworksAnimation>
      {isFramesLoaded && <StyledAnimation animation={memoizedAnimation} />}
    </StyledFireworksAnimation>
  )
}

const StyledFireworksAnimation = styled.div`
  width: 370px;
  height: 200px;
  position: absolute;
  z-index: 3;
  top: -110px;
`

const StyledAnimation = styled.div<StyledAnimationProps>`
  width: 100%;
  height: 100%;
  animation: ${props => props.animation} 5s linear;
  animation-fill-mode: forwards;
`

export default FireworksAnimation