From f9a1af43f553266bfec10d77bfd1a528b8a7ecf1 Mon Sep 17 00:00:00 2001 From: ljpark Date: Wed, 18 Mar 2026 17:45:29 +0900 Subject: [PATCH] sn: zoom level --- apps/dm/app/(popup-layout)/map/popup/page.tsx | 1 + apps/fo/app/pages/(map-layout)/map/page.tsx | 1 + apps/sn/app/(map-layout)/map/page.tsx | 1 + apps/wr/app/(map-layout)/map/mainMap/page.tsx | 1 + .../app/(popUp-layout)/mapDrgtPopUp/page.tsx | 1 + apps/wr/app/(popUp-layout)/splyPopup/page.tsx | 1 + .../business_components/src/ui/map/Gis.js | 3 + .../src/ui/map/GisZoomLevel.js | 80 +++++++++++++++++ .../src/ui/map/lib/css/gis.common.css | 86 +++++++++++++++++++ 9 files changed, 175 insertions(+) create mode 100644 packages/common/business_components/src/ui/map/GisZoomLevel.js diff --git a/apps/dm/app/(popup-layout)/map/popup/page.tsx b/apps/dm/app/(popup-layout)/map/popup/page.tsx index ea1e4b174..e410ad2a7 100644 --- a/apps/dm/app/(popup-layout)/map/popup/page.tsx +++ b/apps/dm/app/(popup-layout)/map/popup/page.tsx @@ -235,6 +235,7 @@ const Map = () => { <>
{ return (
{ setIsPlaying={setIsPlaying as any} targetLayerTypes={WATER_DEPTH_LAYER_TYPES as any} checkInterval={2500} + showZoomLevel={true} defaultZoom={7.5} defaultLonLat={[127.75, 36]} diff --git a/apps/wr/app/(map-layout)/map/mainMap/page.tsx b/apps/wr/app/(map-layout)/map/mainMap/page.tsx index 927703ad9..652fe1924 100644 --- a/apps/wr/app/(map-layout)/map/mainMap/page.tsx +++ b/apps/wr/app/(map-layout)/map/mainMap/page.tsx @@ -388,6 +388,7 @@ const Map = () => { return (
{ <>
)} + {showZoomLevel && }
diff --git a/packages/common/business_components/src/ui/map/GisZoomLevel.js b/packages/common/business_components/src/ui/map/GisZoomLevel.js new file mode 100644 index 000000000..2d1f2848f --- /dev/null +++ b/packages/common/business_components/src/ui/map/GisZoomLevel.js @@ -0,0 +1,80 @@ +import React, { useEffect, useState } from 'react'; +import { useGisContext } from './Gis'; + +export default React.memo(function GisZoomLevel() { + const { gisMap } = useGisContext(); + const [zoomInfo, setZoomInfo] = useState({ + zoom: 0, + minZoom: 0, + maxZoom: 0, + }); + + useEffect(() => { + if (!gisMap) return undefined; + + const view = gisMap.getView(); + if (!view) return undefined; + + const updateZoomInfo = () => { + setZoomInfo({ + zoom: view.getZoom() ?? 0, + minZoom: view.getMinZoom?.() ?? 0, + maxZoom: view.getMaxZoom?.() ?? 20, + }); + }; + + updateZoomInfo(); + view.on('change:resolution', updateZoomInfo); + + return () => { + view.un('change:resolution', updateZoomInfo); + }; + }, [gisMap]); + + if (!gisMap) return <>; + + const { zoom, minZoom, maxZoom } = zoomInfo; + const range = Math.max(maxZoom - minZoom, 1); + const normalized = Math.min(Math.max((zoom - minZoom) / range, 0), 1); + const fillHeight = `${normalized * 100}%`; + const thumbBottom = `calc(${fillHeight} - 1px)`; + + const zoomIn = () => { + const view = gisMap.getView(); + if (view.getMaxZoom() > view.getZoom()) { + view.animate({ + zoom: view.getZoom() + 1, + duration: 250, + }); + } + }; + + const zoomOut = () => { + const view = gisMap.getView(); + if (view.getMinZoom() < view.getZoom()) { + view.animate({ + zoom: view.getZoom() - 1, + duration: 250, + }); + } + }; + + return ( +
+
+ +
+
+
+
+
+
+ +
+
+ ); +}); diff --git a/packages/common/business_components/src/ui/map/lib/css/gis.common.css b/packages/common/business_components/src/ui/map/lib/css/gis.common.css index f9b67a07b..7158fdbec 100644 --- a/packages/common/business_components/src/ui/map/lib/css/gis.common.css +++ b/packages/common/business_components/src/ui/map/lib/css/gis.common.css @@ -173,6 +173,92 @@ text-indent: -9999px; } +.zoom-level-control { + position: absolute; + right: 20px; + bottom: 60px; + z-index: 2; +} + +.zoom-level-panel { + overflow: hidden; + width: 40px; + background: #fff; + border: 1px solid #9aa7b8; + border-radius: 3px; + box-shadow: 0px 0px 5px #999; + box-sizing: border-box; +} + +.zoom-level-btn { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + padding: 0; + border: 0; + border-bottom: 1px solid #eeeeee; + background: #fff; + color: #333; + font-size: 26px; + line-height: 1; + cursor: pointer; +} + +.zoom-level-panel .zoom-level-btn:last-child { + border-top: 1px solid #eeeeee; + border-bottom: 0 none; +} + +.zoom-level-btn:hover { + background: #67aee3; + color: #fff; +} + +.zoom-level-gauge { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 128px; + background: #fff; +} + +.zoom-level-track { + position: relative; + width: 12px; + height: 96px; + border-radius: 6px; + background: + repeating-linear-gradient( + to top, + transparent 0, + transparent 8px, + #d9d9d9 8px, + #d9d9d9 9px + ), + linear-gradient(to top, #f5f5f5, #fafafa); +} + +.zoom-level-fill { + position: absolute; + left: 5px; + bottom: 0; + width: 2px; + background: #3b82f6; + border-radius: 999px; +} + +.zoom-level-thumb { + position: absolute; + left: 50%; + width: 22px; + height: 2px; + background: #111; + transform: translateX(-50%); +} + .ol-scale-line { background: rgba(0, 60, 136, 0.3); border-radius: 4px;