React Hooks로 CSS 그리드에 애니메이션 요소 만들기
grid-row
와 grid-columns
는 트랜지션이 불가능하여 움직이는 애니메이션 요소를 생성하기 어렵습니다.계산을 위해 요소 생성을 사용하여 활성화하는 것을 발견했습니다.
예를 들어 UpLabs SmoothBottomBar을 재현하려고 합니다.
그리고 그것은 성공할 수 있습니다
demo & Full Source Code
메이킹 스텝
1. 기본 그리드 생성
먼저 맨 띠를 만듭니다.
시사
전체 코드
https://stackblitz.com/edit/react-ts-animation-grid-1
설명
메인 그리드는 여기입니다. 나는
react-icons
을 사용합니다. 매우 유용합니다.그
icons
배열은 까다로울 수 있습니다.import { FiUser, FiHome, FiInbox } from "react-icons/fi"
export const Menu1 = () => {
const icons = [FiHome, FiInbox, FiUser]
return (
<Container>
<MenuGrid>
{icons.map((Icon) => (
<IconWrap>
<Icon />
</IconWrap>
))}
</MenuGrid>
</Container>
)
}
2. 계산할 요소를 만듭니다.
다음으로 계산을 위해 셀을 추가합니다.
시사
전체 코드
https://stackblitz.com/edit/react-ts-animation-grid-2
설명
그리드 열에 아이콘을 추가하고 셀 위치 상태 가져오기를 추가해야 합니다.
// Item got props that passed to `grid-column`
const Item = styled.div`
${({ x }) => css`
grid-column: ${x};
`}
grid-row: 1;
`
export const Menu2 = () => {
const [gridPosition, setGridPosition] = useState<number>(1)
// ...
{icons.map((Icon, i) => (
<Item x={i + 1} onMouseOver={(e) => setGridPosition(i + 1)}>
<IconWrap>
<Icon />
</IconWrap>
</Item>
))}
// ...
}
이름이
PositionCalcurator
인 셀을 추가합니다.
// PositionCalcurator extends Item. That can set row and cell.
const PositionCalcurator = styled(Item)`
border: 1px solid red; // for debug
`
export const Menu2 = () => {
const [gridPosition, setGridPosition] = useState<number>(1)
const calcuratorRef = useRef<HTMLElement>(null) // calucrator has `ref`
const icons = [FiHome, FiInbox, FiUser]
return (
<Container>
{/* ... */}
<PositionCalcurator ref={calcuratorRef} x={gridPosition} />
{/* ... */}
</Container>
)
}
3. 애니메이션 커서를 추가합니다.
다음으로 호버 커서를 추가합니다.
시사
전체 코드
https://stackblitz.com/edit/react-ts-animation-grid-3
설명
ref
를 PositionCalcurator
로 설정했습니다. 이제 그리드 위치와 동일한 계산된 refs rect 위치를 얻을 수 있습니다.나는
cursorRect
상태를 생성하고 useEffect
와 연결합니다. 이 효과는 변경 시 호출됩니다gridPosition
.(그러나 사용 시 경고될 수 있습니다eslint-plugin-react-hooks
)export const Menu3 = () => {
const [gridPosition, setGridPosition] = useState<number>(1)
const [cursorRect, setCursor] = useState<null | Rect>(null) // append
const calcuratorRef = useRef<HTMLElement>(null)
useEffect(() => {
if (!calcuratorRef.current) return
const top = calcuratorRef.current.offsetTop
const left = calcuratorRef.current.offsetLeft
const width = calcuratorRef.current.clientWidth
const height = calcuratorRef.current.clientHeight
const cursor = { top, left, width, height }
setCursor(cursor)
}, [gridPosition])
Cursor
를 통과한 cursorRect
구성 요소를 추가합니다. 이 요소는 그리드 및 세트position:absolute
및 애니메이션 속성과 격리되어 있기 때문에 애니메이션을 활성화합니다.
const Cursor = styled.div`
position: absolute;
transition: 0.4s;
transition-timing-function: ease-in-out;
background: green;
opacity: 0.5;
${({ top, left, width, height }) => css`
top: ${top}px;
left: ${left}px;
width: ${width}px;
height: ${height}px;
`};
`
export const Menu3 = () => {
const [cursorRect, setCursor] = useState<null | Rect>(null) // append
// ...
return (
<Container>
{/* Append first for z-index! */}
{cursorRect && <Cursor {...cursorRect} />}
<Cursor>
는 z-인덱스 때문에 Container
에 첫 번째 요소가 필요합니다.4. 텍스트 애니메이션.
이것은 관련 그리드 애니메이션이 아니지만 원본을 따릅니다.
시사
전체 대구
https://stackblitz.com/edit/react-ts-animation-grid-4
설명
:hover
의사만 사용하고 싶지만 커서 상태와 동기화할 수 없기 때문에 active
소품을 추가합니다.export const Menu4 = () => {
const [gridPosition, setGridPosition] = useState<number>(1)
const isActive = useCallback((x) => gridPosition === x, [gridPosition])
const icons = [["Home", FiHome], ["Inbox", FiInbox], ["Profile", FiUser]]
return (
{/* ... */}
{icons.map(([text, Icon], i) => (
<Item x={i + 1} onMouseOver={(e) => setGridPosition(i + 1)}>
<AnimateIcon
x={i + 1}
onMouseOver={(e) => setGridPosition(i + 1)}
text={text}
active={isActive(i + 1)}
>
<Icon />
</AnimateIcon>
</Item>
))}
)
그리고 변화
AnimateIcon
const AnimateIconInner = styled(IconWrap)`
transition: 0.5s;
::after {
font-size: 0.6em;
transition: 0.5s;
overflow: hidden;
content: attr(data-text);
${({ active }) => css`
width: ${active ? "100%" : "0px"};
`}
}
`
const AnimationContainer = styled.div`
width: auto;
`
const AnimateIcon = ({ x, onMouseOver, active, children, text }) => {
return (
<Item x={x} onMouseOver={onMouseOver}>
<AnimateIconInner active={active} data-text={text}>
<AnimationContainer>{children}</AnimationContainer>
</AnimateIconInner>
</Item>
)
}
5. 터닝 및 마감.
버전이 바뀌었습니다(첫 번째 데모와 동일).
전체 코드: https://stackblitz.com/edit/react-ts-animation-grid-final
결론
원시 CSS로 움직이는 CSS 그리드를 찾을 수 없습니다.
한편, 그리드를 좌표 계산으로 사용할 수 있다는 것은 유용할 것 같습니다.
록맨 스테이지 셀렉트와 같은 또 다른 패턴을 만듭니다.
https://amination-grid-menu.netlify.com/
CSS 그리드로 행복한 애니메이션!
Reference
이 문제에 관하여(React Hooks로 CSS 그리드에 애니메이션 요소 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/terrierscript/create-animating-element-on-css-grid-with-react-hooks-50g9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)