Skip to content

Commit

Permalink
fix(emoji): useLayoutWidth를 추가해 목표된 엘리먼트의 width를 활용한 이모지 랜덤 x축 위치 수정,…
Browse files Browse the repository at this point in the history
… PC화면에서 이모지 안나올 수 잇는 가능성 제거
  • Loading branch information
manudeli committed Sep 2, 2022
1 parent a2ef4e0 commit 2d5cd8e
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 40 deletions.
15 changes: 9 additions & 6 deletions components/domains/Emoji/Emojis.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { motion } from "framer-motion";
import { useRecoilValue } from "recoil";
import { Book, Heart, MirrorBall, Note } from "~/assets/svgs";
import { useLayoutWidth } from "~/components/uis/Layout";
import { emojiAtomState } from "~/store/emoji";

const Emojis = ({ stage }: { stage: 1 | 2 | 3 }) => {
Expand All @@ -19,9 +20,11 @@ export default Emojis;

export const EmojiScaled = ({ stage }: { stage: 1 | 2 | 3 }) => {
const emoji = useRecoilValue(emojiAtomState);
const getRandomHalfToFull = () => Math.random() / 4 + 3 / 4;
const getRandom3QuarterToFull = () => Math.random() / 4 + 3 / 4;
const randomMinus = Math.random() > 0.5 ? 1 : -1;

const { width } = useLayoutWidth();

const EmojiSVG = emoji
? emoji.emojiType === "HEART"
? Heart
Expand All @@ -40,16 +43,16 @@ export const EmojiScaled = ({ stage }: { stage: 1 | 2 | 3 }) => {
marginBottom: stage === 3 ? 140 : 1,
}}
initial={{
x: (randomMinus * window.innerWidth * Math.random()) / 2,
y: 400 * getRandomHalfToFull(),
x: (randomMinus * width * Math.random()) / 2,
y: 400 * getRandom3QuarterToFull(),
}}
animate={{
x: (randomMinus * window.innerWidth * Math.random()) / 2,
y: -2000 * getRandomHalfToFull(),
x: (randomMinus * width * Math.random()) / 2,
y: -2000 * getRandom3QuarterToFull(),

opacity: Math.random() * 0.9 + 0.1,
}}
transition={{ duration: 3 * getRandomHalfToFull() }}
transition={{ duration: 3 * getRandom3QuarterToFull() }}
>
<EmojiSVG animate={{ scale: stage === 1 ? 0.6 : stage * stage * 0.4 }} />
</motion.div>
Expand Down
81 changes: 47 additions & 34 deletions components/uis/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,58 @@
import React from "react";
import styled from "@emotion/styled";
import React, { createContext, useContext } from "react";
import { css } from "@emotion/react";
import { useElementSize } from "~/hooks/commons";

const Context = createContext({ width: 450 });
export const useLayoutWidth = () => useContext(Context);

interface Props {
children: React.ReactNode;
screenColor?: string;
}

function Layout({ children, screenColor = "#000000" }: Props) {
return (
<S.Container>
<S.Screen screenColor={screenColor}>{children}</S.Screen>
</S.Container>
);
}
const Layout = ({ children, screenColor = "#000000" }: Props) => {
const [ref, size] = useElementSize();

const S = {
Container: styled.div`
height: 100%;
width: 100%;
max-height: 100%;
z-index: 100;
display: flex;
justify-content: center;
`,

Screen: styled.div<{ screenColor?: string }>`
max-width: 450px;
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
background: ${(p) => p.screenColor};
color: #fff;
position: relative;
backdrop-filter: blur(10px);
return (
<Context.Provider
value={{
width: size.width,
}}
>
<div
css={css`
height: 100%;
width: 100%;
max-height: 100%;
z-index: 100;
display: flex;
justify-content: center;
`}
>
<div
ref={ref}
css={css`
max-width: 450px;
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: hidden;
background: ${screenColor};
color: #fff;
position: relative;
backdrop-filter: blur(10px);
::-webkit-scrollbar {
width: 0;
height: 0;
}
`,
::-webkit-scrollbar {
width: 0;
height: 0;
}
`}
>
{children}
</div>
</div>
</Context.Provider>
);
};

export default Layout;
2 changes: 2 additions & 0 deletions hooks/commons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export { default as useLongPress } from "./useLongPress";
export { default as useDisclosure } from "./useDisclosure";
export { default as useThrottle } from "./useThrottle";
export { default as useIsMobile } from "./useIsMobile";
export { default as useElementSize } from "./useElementSize";
export { default as useEventListener } from "./useEventListener";
36 changes: 36 additions & 0 deletions hooks/commons/useElementSize/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useCallback, useState } from "react";
import useEventListener from "../useEventListener";
import useIsomorphicLayoutEffect from "../useIsomorphicLayoutEffect";

interface Size {
width: number;
height: number;
}

function useElementSize<T extends HTMLElement = HTMLDivElement>(): [
(node: T | null) => void,
Size
] {
const [ref, setRef] = useState<T | null>(null);
const [size, setSize] = useState<Size>({
width: 0,
height: 0,
});

const handleSize = useCallback(() => {
setSize({
width: ref?.offsetWidth || 0,
height: ref?.offsetHeight || 0,
});
}, [ref?.offsetHeight, ref?.offsetWidth]);

useEventListener("resize", handleSize);

useIsomorphicLayoutEffect(() => {
handleSize();
}, [ref?.offsetHeight, ref?.offsetWidth]);

return [setRef, size];
}

export default useElementSize;
64 changes: 64 additions & 0 deletions hooks/commons/useEventListener/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { RefObject } from "react";
import { useEffect, useRef } from "react";
import useIsomorphicLayoutEffect from "../useIsomorphicLayoutEffect";

function useEventListener<K extends keyof WindowEventMap>(
eventName: K,
handler: (event: WindowEventMap[K]) => void,
element?: undefined,
options?: boolean | AddEventListenerOptions
): void;

function useEventListener<
K extends keyof HTMLElementEventMap,
T extends HTMLElement = HTMLDivElement
>(
eventName: K,
handler: (event: HTMLElementEventMap[K]) => void,
element: RefObject<T>,
options?: boolean | AddEventListenerOptions
): void;

function useEventListener<K extends keyof DocumentEventMap>(
eventName: K,
handler: (event: DocumentEventMap[K]) => void,
element: RefObject<Document>,
options?: boolean | AddEventListenerOptions
): void;

function useEventListener<
KW extends keyof WindowEventMap,
KH extends keyof HTMLElementEventMap,
T extends HTMLElement | void = void
>(
eventName: KW | KH,
handler: (
event: WindowEventMap[KW] | HTMLElementEventMap[KH] | Event
) => void,
element?: RefObject<T>,
options?: boolean | AddEventListenerOptions
) {
const savedHandler = useRef(handler);

useIsomorphicLayoutEffect(() => {
savedHandler.current = handler;
}, [handler]);

useEffect(() => {
const targetElement: T | Window = element?.current || window;
if (!(targetElement && targetElement.addEventListener)) {
return;
}

const eventListener: typeof handler = (event) =>
savedHandler.current(event);

targetElement.addEventListener(eventName, eventListener, options);

return () => {
targetElement.removeEventListener(eventName, eventListener);
};
}, [eventName, element, options]);
}

export default useEventListener;

0 comments on commit 2d5cd8e

Please sign in to comment.