How to animate an image to the center of the page in react

314 views Asked by At

I have avatar images that I want to expand and bring to the center on click. For that I'm using translate and scale:

import React, { useEffect, useRef, useState } from "react"
import { Transition } from "react-transition-group"

function UserItem({ firstName, lastName, email, avatar, isInGrid }) {
  const [isAvatarModalOpen, setIsAvatarModalOpen] = useState(false)
  const avatarEl = useRef(null)
  const animationRef = useRef({})

  useEffect(() => {
    const { x, y, width } = avatarEl.current.getBoundingClientRect()
    const toDimensions = Math.min(window.innerWidth, window.innerHeight, 350)
    const translateX = window.innerWidth / 2 - toDimensions / 2 - x
    const translateY = window.innerHeight / 2 - toDimensions / 2 - y
    const scale = toDimensions / width
    animationRef.current = { translateX, translateY, scale }
  }, [])

  const handleAvatarClick = () => {
    setIsAvatarModalOpen(!isAvatarModalOpen)
  }

  const transitionStyles = {
    entering: {
      transform: `scale(${animationRef.current.scale}) translate(${animationRef.current.translateX}px, ${animationRef.current.translateY}px)`,
    },
    entered: {
      transform: `scale(${animationRef.current.scale}) translate(${animationRef.current.translateX}px, ${animationRef.current.translateY}px)`,
    },
    exiting: { transform: "translate(0, 0) scale(1)" },
    exited: { transform: "translate(0, 0) scale(1)" },
  }

  return (
    <Transition in={isAvatarModalOpen} timeout={300}>
      {state => {
        return (
          <img
            style={{
              transition: "transform 300ms",
              ...transitionStyles[state],
            }}
            onClick={handleAvatarClick}
            ref={avatarEl}
            src={avatar}
          />
        )
      }}
    </Transition>
  )
}

export default UserItem

ATM this is what happens:

enter image description here

So what am I missing? Are my calculations off?

Here's a sandbox

Thanks in advance!

0

There are 0 answers