sn: 침수흔적심선/위선 화살표 연속 scroll 추가
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import type { RefObject } from "react";
|
||||
import GisApp from "@common/business_components/ui/map/lib/gis.core";
|
||||
import type Feature from "ol/Feature.js";
|
||||
import VectorSource from "ol/source/Vector.js";
|
||||
@@ -29,6 +30,96 @@ type FldngHstryGisLayer = {
|
||||
) => void | Promise<void>;
|
||||
};
|
||||
|
||||
type FldngHstryScrollButtonProps = {
|
||||
targetRef: RefObject<HTMLDivElement | null>;
|
||||
direction: -1 | 1;
|
||||
label: string;
|
||||
children: string;
|
||||
};
|
||||
|
||||
const FLDNG_HSTRY_SCROLL_CLICK_DISTANCE = 120;
|
||||
const FLDNG_HSTRY_SCROLL_HOLD_DELAY = 300;
|
||||
const FLDNG_HSTRY_SCROLL_HOLD_SPEED = 4;
|
||||
|
||||
/** 짧게 누르면 한 칸, 길게 누르면 목록을 해당 방향으로 계속 이동한다. */
|
||||
const FldngHstryScrollButton = ({
|
||||
targetRef,
|
||||
direction,
|
||||
label,
|
||||
children,
|
||||
}: FldngHstryScrollButtonProps) => {
|
||||
const holdTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const animationFrameRef = useRef<number | null>(null);
|
||||
const pointerClickHandledRef = useRef(false);
|
||||
|
||||
const stopContinuousScroll = useCallback(() => {
|
||||
if (holdTimerRef.current !== null) {
|
||||
clearTimeout(holdTimerRef.current);
|
||||
holdTimerRef.current = null;
|
||||
}
|
||||
if (animationFrameRef.current !== null) {
|
||||
cancelAnimationFrame(animationFrameRef.current);
|
||||
animationFrameRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const scrollOnce = useCallback(() => {
|
||||
targetRef.current?.scrollBy({
|
||||
left: direction * FLDNG_HSTRY_SCROLL_CLICK_DISTANCE,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}, [direction, targetRef]);
|
||||
|
||||
const startContinuousScroll = useCallback(() => {
|
||||
const scroll = () => {
|
||||
const target = targetRef.current;
|
||||
if (!target) {
|
||||
stopContinuousScroll();
|
||||
return;
|
||||
}
|
||||
target.scrollLeft += direction * FLDNG_HSTRY_SCROLL_HOLD_SPEED;
|
||||
animationFrameRef.current = requestAnimationFrame(scroll);
|
||||
};
|
||||
animationFrameRef.current = requestAnimationFrame(scroll);
|
||||
}, [direction, stopContinuousScroll, targetRef]);
|
||||
|
||||
useEffect(() => stopContinuousScroll, [stopContinuousScroll]);
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={label}
|
||||
className="shrink-0 select-none px-1 text-lg leading-none text-foreground"
|
||||
onPointerDown={(event) => {
|
||||
if (event.button !== 0) return;
|
||||
stopContinuousScroll();
|
||||
pointerClickHandledRef.current = true;
|
||||
event.currentTarget.setPointerCapture(event.pointerId);
|
||||
scrollOnce();
|
||||
holdTimerRef.current = setTimeout(
|
||||
startContinuousScroll,
|
||||
FLDNG_HSTRY_SCROLL_HOLD_DELAY,
|
||||
);
|
||||
}}
|
||||
onPointerUp={stopContinuousScroll}
|
||||
onPointerCancel={() => {
|
||||
stopContinuousScroll();
|
||||
pointerClickHandledRef.current = false;
|
||||
}}
|
||||
onLostPointerCapture={stopContinuousScroll}
|
||||
onClick={() => {
|
||||
if (pointerClickHandledRef.current) {
|
||||
pointerClickHandledRef.current = false;
|
||||
return;
|
||||
}
|
||||
scrollOnce();
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
const cloneFldngHstryFeature = (feature: Feature) => {
|
||||
const clonedFeature = feature.clone();
|
||||
const featureId = feature.getId();
|
||||
@@ -171,19 +262,13 @@ export const useFldngHstryFeatureClick = () => {
|
||||
<span className="w-9 shrink-0 text-[1.1rem] font-semibold">
|
||||
심선
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="이전 연도"
|
||||
className="shrink-0 px-1 text-lg leading-none text-foreground"
|
||||
onClick={() =>
|
||||
fldngHstryDepthYearListRef.current?.scrollBy({
|
||||
left: -120,
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
<FldngHstryScrollButton
|
||||
targetRef={fldngHstryDepthYearListRef}
|
||||
direction={-1}
|
||||
label="이전 연도"
|
||||
>
|
||||
‹
|
||||
</button>
|
||||
</FldngHstryScrollButton>
|
||||
<div
|
||||
ref={fldngHstryDepthYearListRef}
|
||||
className="flex min-w-0 flex-1 gap-2 overflow-x-auto whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
||||
@@ -231,19 +316,13 @@ export const useFldngHstryFeatureClick = () => {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="다음 연도"
|
||||
className="shrink-0 px-1 text-lg leading-none text-foreground"
|
||||
onClick={() =>
|
||||
fldngHstryDepthYearListRef.current?.scrollBy({
|
||||
left: 120,
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
<FldngHstryScrollButton
|
||||
targetRef={fldngHstryDepthYearListRef}
|
||||
direction={1}
|
||||
label="다음 연도"
|
||||
>
|
||||
›
|
||||
</button>
|
||||
</FldngHstryScrollButton>
|
||||
</div>
|
||||
)}
|
||||
{fldngHstryWtlvRows.length > 0 && (
|
||||
@@ -251,19 +330,13 @@ export const useFldngHstryFeatureClick = () => {
|
||||
<span className="w-9 shrink-0 text-[1.1rem] font-semibold">
|
||||
위선
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="이전 위선"
|
||||
className="shrink-0 px-1 text-lg leading-none text-foreground"
|
||||
onClick={() =>
|
||||
fldngHstryWtlvListRef.current?.scrollBy({
|
||||
left: -120,
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
<FldngHstryScrollButton
|
||||
targetRef={fldngHstryWtlvListRef}
|
||||
direction={-1}
|
||||
label="이전 위선"
|
||||
>
|
||||
‹
|
||||
</button>
|
||||
</FldngHstryScrollButton>
|
||||
<div
|
||||
ref={fldngHstryWtlvListRef}
|
||||
className="flex min-w-0 flex-1 gap-2 overflow-x-auto whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
|
||||
@@ -295,19 +368,13 @@ export const useFldngHstryFeatureClick = () => {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="다음 위선"
|
||||
className="shrink-0 px-1 text-lg leading-none text-foreground"
|
||||
onClick={() =>
|
||||
fldngHstryWtlvListRef.current?.scrollBy({
|
||||
left: 120,
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
<FldngHstryScrollButton
|
||||
targetRef={fldngHstryWtlvListRef}
|
||||
direction={1}
|
||||
label="다음 위선"
|
||||
>
|
||||
›
|
||||
</button>
|
||||
</FldngHstryScrollButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -292,9 +292,14 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.zoom-level-panel .zoom-level-btn:first-child {
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.zoom-level-panel .zoom-level-btn:last-child {
|
||||
border-top: 1px solid #eeeeee;
|
||||
border-bottom: 0 none;
|
||||
border-radius: 0 0 3px 3px;
|
||||
}
|
||||
|
||||
.zoom-level-btn:hover {
|
||||
|
||||
Reference in New Issue
Block a user