LoginSignup
10
2

More than 1 year has passed since last update.

Chakra UI のModalOverlay を使ってローディングアニメーションを作成

Posted at

概要

趣味でローディングアニメーションを作成したのですが、使わなくなったので、こちらにて供養したいと思います。

Requirement

  • Framer Motion
  • Chakra UI

Framer Motion x Chakra UI を使うためのコンポーネントの作成

↑を参考に、以下のようなコンポーネントをつくります。

motion-box.tsx
import { motion, HTMLMotionProps } from 'framer-motion'
import { chakra, HTMLChakraProps } from '@chakra-ui/react'
type Merge<P, T> = Omit<P, keyof T> & T
type MotionBoxProps = Merge<HTMLChakraProps<'div'>, HTMLMotionProps<'div'>>

export const MotionBox: React.FC<MotionBoxProps> = motion(chakra.div)

もしくは、

上記の motion-box については公式のようなコンポーネントの作り方でもOK。
(私は好みで前者の方をつかいました)

ローディングアニメーション

loading-modal.tsx
import { MotionBox } from './motion-box'

import {
  Modal,
  Box,
  ModalOverlay,
  useBreakpointValue
} from '@chakra-ui/react'

const LoadingCircle = ({ animateScale }: {animateScale: Array<number>}) => {
  return (
    <MotionBox 
      width={'30px'}
      height={'30px'}
      borderRadius={'50%'}
      mr={6}
      ml={-3}
      bg={'white'}
      animate={{scale: animateScale}}
      transition={{
        duration: 1.5,
        ease: "linear",
        repeat: Infinity,
        repeatType: "reverse",
      }}
    />
  )
}

export const LoadingModal = ({ isOpen, onClose }: { isOpen: boolean, onClose: () => void}) => {
  const isPc = useBreakpointValue({base: false, md: true})
  return (
    <>
      <Modal isOpen={isOpen} onClose={onClose} scrollBehavior={'inside'} size={'xl'}>
        <Box position={'relative'}>
          <ModalOverlay>
            <Box
              display={'flex'}
              position={'absolute'}
              zIndex={10000} // ModalOverlayが 1300 程度
              top={'50%'}
              left={isPc ? '50%' : '40vw'}
            >
              <LoadingCircle
                animateScale={
                  [2, 1, 1]
                }
              />
              <LoadingCircle
                animateScale={
                  [1, 2, 1]
                }
              />
              <LoadingCircle
                animateScale={
                  [1, 1, 2]
                }
              />
            </Box>
          </ModalOverlay>
        </Box>
      </Modal>
    </>
  )
}

使い方

Chakra UI の useDisclosure() を使って、簡単に実装できます。

.tsx
import { useDisclosure } from '@chakra-ui/react'

export SampleComponent () => {
  const { isOpen, onOpen, onClose } = useDisclosure()

// 例えばページの遷移ならそれ依存配列に入れる

  useEffect(()=>{
    onClose()
  }, [])

// 何かしらをトリガーにしてアニメーションを表示
  const onClick = () => {
    ...
    onOpen()
  }
 
  return (
    <>
      ...
      <LoadingModal isOpen={isOpen} onClose={onClose} />
    </>
  )

}

↓こんな感じになります
hoge.gif

10
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
2