sn: zoom level
This commit is contained in:
@@ -235,6 +235,7 @@ const Map = () => {
|
||||
<>
|
||||
<div className="bg-container">
|
||||
<Gis
|
||||
showZoomLevel={true}
|
||||
height='h-screen'
|
||||
treeData={treeData}
|
||||
isSearch={false}
|
||||
|
||||
@@ -295,6 +295,7 @@ const Map = () => {
|
||||
return (
|
||||
<div className="bg-container">
|
||||
<Gis
|
||||
showZoomLevel={true}
|
||||
treeData={treeData}
|
||||
isSearch={false}
|
||||
gisMaps={gisMaps}
|
||||
|
||||
@@ -171,6 +171,7 @@ const Map = () => {
|
||||
setIsPlaying={setIsPlaying as any}
|
||||
targetLayerTypes={WATER_DEPTH_LAYER_TYPES as any}
|
||||
checkInterval={2500}
|
||||
showZoomLevel={true}
|
||||
|
||||
defaultZoom={7.5}
|
||||
defaultLonLat={[127.75, 36]}
|
||||
|
||||
@@ -388,6 +388,7 @@ const Map = () => {
|
||||
return (
|
||||
<div className="bg-container">
|
||||
<Gis
|
||||
showZoomLevel={true}
|
||||
treeData={treeData}
|
||||
isSearch={false}
|
||||
gisMaps={gisMaps}
|
||||
|
||||
@@ -58,6 +58,7 @@ export default function MapDrgtPopUp() {
|
||||
return (
|
||||
<div className="bg-container">
|
||||
<Gis
|
||||
showZoomLevel={true}
|
||||
treeData={treeData}
|
||||
isSearch={false}
|
||||
gisMaps={gisMaps}
|
||||
|
||||
@@ -277,6 +277,7 @@ const Map = () => {
|
||||
<>
|
||||
<div className="bg-container">
|
||||
<Gis
|
||||
showZoomLevel={true}
|
||||
height='h-screen'
|
||||
treeData={treeData}
|
||||
isSearch={false}
|
||||
|
||||
@@ -19,6 +19,7 @@ import GisMapToggle from "./GisMapToggle";
|
||||
import GisSelect from "./GisSelect";
|
||||
import GisToolBar from "./GisToolBar";
|
||||
import GisTree from "./GisTree";
|
||||
import GisZoomLevel from "./GisZoomLevel";
|
||||
import "./lib/css/gis.common.css";
|
||||
import GisApp from "./lib/gis.core";
|
||||
import LoadingOverlay from "@common/business_components/ui/loadingBar";
|
||||
@@ -58,6 +59,7 @@ function Gis({
|
||||
droughtDates = { startYmd: '', endYmd: '' },
|
||||
defaultZoom = 15,
|
||||
defaultLonLat = [127.4875, 37.4916],
|
||||
showZoomLevel = false,
|
||||
}) {
|
||||
const mapRef = useRef();
|
||||
const [mapObject, setMapObject] = useState({});
|
||||
@@ -325,6 +327,7 @@ function Gis({
|
||||
</div>
|
||||
)}
|
||||
<GisToolBar />
|
||||
{showZoomLevel && <GisZoomLevel />}
|
||||
<GisMapToggle />
|
||||
<GisSelect onFeatureSelect={handleFeatureSelect} />
|
||||
</div>
|
||||
|
||||
@@ -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 (
|
||||
<div className="zoom-level-control" title={`현재 줌 레벨 ${zoom.toFixed(1)}`}>
|
||||
<div className="zoom-level-panel">
|
||||
<button type="button" className="zoom-level-btn" onClick={zoomIn} aria-label="확대">
|
||||
+
|
||||
</button>
|
||||
<div className="zoom-level-gauge">
|
||||
<div className="zoom-level-track">
|
||||
<div className="zoom-level-fill" style={{ height: fillHeight }} />
|
||||
<div className="zoom-level-thumb" style={{ bottom: thumbBottom }} />
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" className="zoom-level-btn" onClick={zoomOut} aria-label="축소">
|
||||
-
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user