From e2cc7a56abf99e3bf52108970f82e0ad4ab6ebe4 Mon Sep 17 00:00:00 2001 From: yoouyeon Date: Sun, 22 Dec 2024 21:59:35 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - f3161845ead11fc5b9f8949d1bcf0ed3610dfb4c - 5d59ee51eaa3e6ecf7ac009d71c3c484a455187a - df4733f808fe9d13d7674ffd7f8ec11a5d183106 --- components/takgu/Layout/MegaPhone.tsx | 71 --------------------------- 1 file changed, 71 deletions(-) diff --git a/components/takgu/Layout/MegaPhone.tsx b/components/takgu/Layout/MegaPhone.tsx index 46bf4d0e2..1997e3dc1 100644 --- a/components/takgu/Layout/MegaPhone.tsx +++ b/components/takgu/Layout/MegaPhone.tsx @@ -14,45 +14,12 @@ interface IMegaphoneContent { type MegaphoneList = Array; -// type MegaphoneContainerProps = { -// children: React.ReactNode; -// count: number; -// }; - const adminContent: IMegaphoneContent = { megaphoneId: 0, content: '상점에서 아이템을 구매해서 확성기를 등록해보세요!(30자 제한)', intraId: '관리자', }; -// export const MegaphoneContainer = ({ -// children, -// count, -// }: MegaphoneContainerProps) => { -// const ref = useRef(null); -// const [selectedIndex, setSelectedIndex] = useState(0); - -// useInterval(() => { -// const nextIndex = (selectedIndex + 1) % count; -// setSelectedIndex(nextIndex); -// }, 4000); - -// return ( -//
-//
-// {children} -//
-//
-// ); -// }; - export const MegaphoneItem = ({ content, intraId }: IMegaphoneContent) => { return (
@@ -143,44 +110,6 @@ const Megaphone = () => {
); - - // return ( - // - // {megaphoneData.map((content, idx) => ( - // - // ))} - // - // ); - - // return contents.length > 0 ? ( - // - // {contents.map((content, idx) => ( - // - // ))} - // - // ) : ( - // - // - // {itemList.map((item, idx) => ( - // - // ))} - // - // ); }; export default Megaphone; From e75de5e1d7fdcf9fa2ba97f0527c7f0bc5c8c9ac Mon Sep 17 00:00:00 2001 From: yoouyeon Date: Sun, 22 Dec 2024 22:01:23 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Fix:=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 유저의 임의 스크롤을 막기 위해서 조치한 것이 정상적인 스크롤 동작을 방해함. --- components/takgu/Layout/MegaPhone.tsx | 8 +------- styles/takgu/Layout/MegaPhone.module.scss | 6 ------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/components/takgu/Layout/MegaPhone.tsx b/components/takgu/Layout/MegaPhone.tsx index 1997e3dc1..e8142cb6c 100644 --- a/components/takgu/Layout/MegaPhone.tsx +++ b/components/takgu/Layout/MegaPhone.tsx @@ -94,16 +94,10 @@ const Megaphone = () => {
{!!megaphoneData && megaphoneData.length > 0 && ( ( - - )} + itemContent={(_, data) => } style={{ height: '100%' }} /> )} diff --git a/styles/takgu/Layout/MegaPhone.module.scss b/styles/takgu/Layout/MegaPhone.module.scss index 805bbd787..99972c775 100644 --- a/styles/takgu/Layout/MegaPhone.module.scss +++ b/styles/takgu/Layout/MegaPhone.module.scss @@ -49,9 +49,3 @@ $bannerHeight: 3rem; justify-content: center; align-items: center; } - -.virtuoso { - // NOTE : 라이브러리에서 인라인 스타일로 overflow-y: auto를 주고 있어 스크롤바가 생김 - // 이를 상쇄하기 위해서 !important를 사용함. - overflow-y: hidden !important; -} From 4b6c2ee3bfd51283dd1f23d8e5a0336305d00670 Mon Sep 17 00:00:00 2001 From: yoouyeon Date: Sun, 22 Dec 2024 22:44:49 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Feat:=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=EB=A5=BC=20=EB=AC=B4=EC=8B=9C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20MegaphoneScroller=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - https://virtuoso.dev/customize-structure/ - https://virtuoso.dev/custom-scroll-container/ - passive 기본값 설정 (true)를 바꾸기 위해 직접 이벤트 리스너를 등록함. --- components/takgu/Layout/MegaPhone.tsx | 74 +++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/components/takgu/Layout/MegaPhone.tsx b/components/takgu/Layout/MegaPhone.tsx index e8142cb6c..6f8df0f75 100644 --- a/components/takgu/Layout/MegaPhone.tsx +++ b/components/takgu/Layout/MegaPhone.tsx @@ -1,6 +1,6 @@ import { useRouter } from 'next/router'; -import { useState, useEffect, useRef } from 'react'; -import { Virtuoso, VirtuosoHandle } from 'react-virtuoso'; +import { useState, useEffect, useRef, forwardRef } from 'react'; +import { Virtuoso, VirtuosoHandle, Components } from 'react-virtuoso'; import { Item } from 'types/takgu/itemTypes'; import useAxiosGet from 'hooks/useAxiosGet'; import useInterval from 'hooks/useInterval'; @@ -20,15 +20,7 @@ const adminContent: IMegaphoneContent = { intraId: '관리자', }; -export const MegaphoneItem = ({ content, intraId }: IMegaphoneContent) => { - return ( -
-
{intraId}
-
{content}
-
- ); -}; - +// 메인 확성기 컴포넌트 const Megaphone = () => { const [contents, setContents] = useState([]); const [itemList, setItemList] = useState([]); @@ -99,6 +91,9 @@ const Megaphone = () => { ref={virtuoso} itemContent={(_, data) => } style={{ height: '100%' }} + components={{ + Scroller: MegaphoneScroller, + }} /> )}
@@ -106,4 +101,61 @@ const Megaphone = () => { ); }; +// 확성기 아이템 컴포넌트 +export const MegaphoneItem = ({ content, intraId }: IMegaphoneContent) => { + return ( +
+
{intraId}
+
{content}
+
+ ); +}; + +// 유저의 스크롤 이벤트 동작을 제거한 확성기 스크롤러 컴포넌트 +const MegaphoneScroller: Components['Scroller'] = forwardRef( + ({ children, ...props }, ref) => { + const localRef = useRef(null); + + // 전달받은 ref와 내부 ref가 동일한 element를 가리키도록 함 + const combinedRef = (node: HTMLDivElement | null) => { + localRef.current = node; + + if (ref) { + (ref as React.MutableRefObject).current = node; + } + }; + + useEffect(() => { + const element = localRef.current; + + if (element) { + const preventScroll = (e: Event) => { + e.preventDefault(); + e.stopPropagation(); + }; + + // wheel 및 touchmove 이벤트 차단 (pc 및 모바일) + element.addEventListener('wheel', preventScroll, { passive: false }); + element.addEventListener('touchmove', preventScroll, { + passive: false, + }); + + // 컴포넌트 언마운트 시 이벤트 제거 + return () => { + element.removeEventListener('wheel', preventScroll); + element.removeEventListener('touchmove', preventScroll); + }; + } + }, []); + + return ( +
+ {children} +
+ ); + } +); + +MegaphoneScroller.displayName = 'MegaphoneScroller'; + export default Megaphone;