Fixed Viewport
This commit is contained in:
parent
900c9fcfca
commit
82c00cc4ba
2 changed files with 552 additions and 152 deletions
27
src/components/UI/Map/OpenLayerMap.css
Normal file
27
src/components/UI/Map/OpenLayerMap.css
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#root {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* For your map container specifically */
|
||||
.map-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Ensure OL map gets proper dimensions */
|
||||
.ol-viewport {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
|
@ -7,33 +7,42 @@ import { fromLonLat } from 'ol/proj';
|
|||
import { Coordinate } from 'ol/coordinate';
|
||||
import VectorLayer from 'ol/layer/Vector';
|
||||
import { layerConfigs } from '../../Methods/Layers';
|
||||
import { loadAndRenderGeoJsonLayer } from '../../Methods/GeoJson_Load'
|
||||
import { loadAndRenderGeoJsonLayer } from '../../Methods/GeoJson_Load';
|
||||
import { addMarker } from '../../Methods/Marker';
|
||||
|
||||
const OpenLayersMap = () => {
|
||||
const [term, setTerm] = useState<string>('');
|
||||
const [address, setAddress] = useState();
|
||||
const [address, setAddress] = useState<any>();
|
||||
const [layerVisibility, setLayerVisibility] = useState<Record<string, boolean>>({});
|
||||
const [searchCompleted, setSearchCompleted] = useState(false);
|
||||
const [sidebarOpen, setSidebarOpen] = useState(true);
|
||||
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
|
||||
|
||||
// Check for mobile view
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
setIsMobile(window.innerWidth < 768);
|
||||
if (window.innerWidth >= 768) {
|
||||
setSidebarOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
// Submit Button Logic
|
||||
const submitForm = async (event: React.FormEvent<HTMLFormElement>) => {
|
||||
// Preventing the page from reloading
|
||||
event.preventDefault();
|
||||
const response = await fetch(`https://nominatim.openstreetmap.org/search?q=${term}&format=json&polygon=1&addressdetails=1`);
|
||||
const json = await response.json();
|
||||
console.log(json);
|
||||
setAddress(json);
|
||||
console.log(address);
|
||||
setSearchCompleted(true);
|
||||
|
||||
// Initialize all layers as visible
|
||||
|
||||
const initialVisibility = Object.fromEntries(
|
||||
layerConfigs.map(layer => [layer.topic, true])
|
||||
);
|
||||
setLayerVisibility(initialVisibility);
|
||||
|
||||
alert(term);
|
||||
}
|
||||
|
||||
const mapDivRef = useRef<HTMLDivElement>(null);
|
||||
|
|
@ -50,11 +59,11 @@ const OpenLayersMap = () => {
|
|||
const toggleLayer = (layerTopic: string) => {
|
||||
const layerRef = layerRefs.current[layerTopic];
|
||||
const isCurrentlyVisible = layerVisibility[layerTopic];
|
||||
|
||||
|
||||
if (layerRef.current) {
|
||||
layerRef.current.setVisible(!isCurrentlyVisible);
|
||||
}
|
||||
|
||||
|
||||
setLayerVisibility(prev => ({
|
||||
...prev,
|
||||
[layerTopic]: !isCurrentlyVisible
|
||||
|
|
@ -88,7 +97,7 @@ const OpenLayersMap = () => {
|
|||
}));
|
||||
|
||||
markerLayerRef.current = addMarker(coords, mapRef.current!, markerLayerRef.current);
|
||||
|
||||
|
||||
layerConfigs.forEach((layerConfig) => {
|
||||
const url = layerConfig.getUrl(lon, lat, layerConfig.radius);
|
||||
const ref = layerRefs.current[layerConfig.topic];
|
||||
|
|
@ -102,171 +111,535 @@ const OpenLayersMap = () => {
|
|||
}
|
||||
}, [address]);
|
||||
|
||||
// UI
|
||||
return (
|
||||
<div style={{ display: 'flex', height: '100vh', width: '100vw' }}>
|
||||
{/* Sidebar */}
|
||||
<div style={{
|
||||
width: '320px',
|
||||
backgroundColor: '#f8f9fa',
|
||||
borderRight: '1px solid #dee2e6',
|
||||
padding: '20px',
|
||||
overflowY: 'auto',
|
||||
boxShadow: '2px 0 5px rgba(0,0,0,0.1)'
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100vh',
|
||||
width: '100vw',
|
||||
fontFamily: "'Poppins', sans-serif",
|
||||
backgroundColor: '#f8f9fa',
|
||||
overflow: 'hidden'
|
||||
}}>
|
||||
{/* Google Fonts Link */}
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<style>
|
||||
{`
|
||||
/* Fix for black borders */
|
||||
body, html, #root {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* Map container fixes */
|
||||
.map-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Layer list improvements */
|
||||
.layer-item {
|
||||
padding: 8px 12px;
|
||||
margin: 2px 0;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.layer-item:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
/* Custom scrollbar */
|
||||
.custom-scrollbar::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.custom-scrollbar::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
.custom-scrollbar::-webkit-scrollbar-thumb {
|
||||
background: #c1c1c1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
|
||||
background: #a1a1a1;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsive styles */
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
position: absolute !important;
|
||||
width: 280px !important;
|
||||
left: ${sidebarOpen ? '0' : '-280px'};
|
||||
z-index: 1000;
|
||||
transition: left 0.3s ease;
|
||||
height: calc(100vh - 72px) !important;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.nav-buttons {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.mobile-menu-btn {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
padding: 0 16px !important;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.header-title {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 260px !important;
|
||||
left: ${sidebarOpen ? '0' : '-260px'};
|
||||
}
|
||||
|
||||
.coordinate-display {
|
||||
bottom: 16px !important;
|
||||
left: 16px !important;
|
||||
right: 16px !important;
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
|
||||
{/* Header */}
|
||||
<header style={{
|
||||
backgroundColor: '#ffffff',
|
||||
borderBottom: '1px solid #e9ecef',
|
||||
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.08)',
|
||||
padding: '0 32px',
|
||||
height: '72px',
|
||||
minHeight: '72px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
position: 'relative',
|
||||
zIndex: 1000,
|
||||
flexShrink: 0
|
||||
}}>
|
||||
<h3 style={{
|
||||
margin: '0 0 20px 0',
|
||||
color: '#333',
|
||||
fontSize: '18px',
|
||||
fontWeight: '600'
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '12px'
|
||||
}}>
|
||||
Map Layers
|
||||
</h3>
|
||||
|
||||
{/* Search Form */}
|
||||
<form onSubmit={submitForm} style={{ marginBottom: '20px' }}>
|
||||
<input
|
||||
value={term}
|
||||
onChange={(e) => setTerm(e.target.value)}
|
||||
type="text"
|
||||
placeholder="Enter address to search"
|
||||
{/* Mobile menu button - hidden on desktop */}
|
||||
<button
|
||||
className="mobile-menu-btn"
|
||||
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '10px',
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '4px',
|
||||
marginBottom: '10px',
|
||||
fontSize: '14px'
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '10px',
|
||||
backgroundColor: '#007bff',
|
||||
color: 'white',
|
||||
display: 'none',
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
fontSize: '20px',
|
||||
cursor: 'pointer',
|
||||
fontSize: '14px',
|
||||
fontWeight: '500'
|
||||
padding: '8px',
|
||||
color: '#2c3e50'
|
||||
}}
|
||||
>
|
||||
Search
|
||||
☰
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* Layer Toggle List */}
|
||||
<div>
|
||||
<h4 style={{
|
||||
margin: '0 0 15px 0',
|
||||
color: '#666',
|
||||
fontSize: '14px',
|
||||
fontWeight: '500',
|
||||
textTransform: 'uppercase',
|
||||
letterSpacing: '0.5px'
|
||||
<div style={{
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
background: 'linear-gradient(135deg, #2c3e50 0%, #34495e 100%)',
|
||||
borderRadius: '12px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
boxShadow: '0 4px 12px rgba(44, 62, 80, 0.15)'
|
||||
}}>
|
||||
Available Layers ({layerConfigs.length})
|
||||
</h4>
|
||||
|
||||
{layerConfigs.map((layer) => (
|
||||
<div key={layer.topic} style={{
|
||||
<span style={{
|
||||
color: 'white',
|
||||
fontSize: '18px',
|
||||
fontWeight: '700'
|
||||
}}>M</span>
|
||||
</div>
|
||||
<span className="header-title" style={{
|
||||
fontSize: '24px',
|
||||
fontWeight: '600',
|
||||
color: '#2c3e50',
|
||||
letterSpacing: '-0.5px'
|
||||
}}>
|
||||
MapExplorer
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Navigation - hidden on mobile */}
|
||||
<nav className="nav-buttons" style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px'
|
||||
}}>
|
||||
{['Home', 'Map', 'About', 'Contact'].map((item, index) => (
|
||||
<button
|
||||
key={item}
|
||||
style={{
|
||||
padding: '12px 20px',
|
||||
backgroundColor: index === 1 ? '#2c3e50' : 'transparent',
|
||||
color: index === 1 ? 'white' : '#495057',
|
||||
border: 'none',
|
||||
borderRadius: '12px',
|
||||
fontSize: '14px',
|
||||
fontWeight: '500',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
boxShadow: index === 1 ? '0 4px 12px rgba(44, 62, 80, 0.2)' : 'none',
|
||||
}}
|
||||
>
|
||||
{item}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '16px'
|
||||
}}>
|
||||
<button style={{
|
||||
padding: '10px',
|
||||
backgroundColor: '#f8f9fa',
|
||||
border: 'none',
|
||||
borderRadius: '10px',
|
||||
cursor: 'pointer',
|
||||
color: '#6c757d',
|
||||
fontSize: '16px',
|
||||
transition: 'all 0.3s ease',
|
||||
}}>
|
||||
🔔
|
||||
</button>
|
||||
<div style={{
|
||||
width: '36px',
|
||||
height: '36px',
|
||||
background: 'linear-gradient(135deg, #6c757d 0%, #8b949e 100%)',
|
||||
borderRadius: '50%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
color: 'white',
|
||||
fontSize: '14px',
|
||||
fontWeight: '600',
|
||||
cursor: 'pointer',
|
||||
boxShadow: '0 3px 8px rgba(108, 117, 125, 0.15)',
|
||||
}}>
|
||||
U
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Main Content */}
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
height: 'calc(100vh - 72px)',
|
||||
width: '100vw',
|
||||
overflow: 'hidden',
|
||||
position: 'relative'
|
||||
}}>
|
||||
{/* Sidebar with responsive behavior */}
|
||||
<div className="sidebar custom-scrollbar" style={{
|
||||
width: '360px',
|
||||
backgroundColor: '#ffffff',
|
||||
borderRight: '1px solid #e9ecef',
|
||||
padding: '24px',
|
||||
overflowY: 'auto',
|
||||
overflowX: 'hidden',
|
||||
boxShadow: '4px 0 16px rgba(0,0,0,0.06)',
|
||||
flexShrink: 0
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '12px',
|
||||
marginBottom: '24px'
|
||||
}}>
|
||||
<div style={{
|
||||
width: '8px',
|
||||
height: '32px',
|
||||
background: 'linear-gradient(135deg, #2c3e50 0%, #34495e 100%)',
|
||||
borderRadius: '4px'
|
||||
}} />
|
||||
<h3 style={{
|
||||
margin: '0',
|
||||
color: '#2c3e50',
|
||||
fontSize: '20px',
|
||||
fontWeight: '600',
|
||||
letterSpacing: '-0.3px'
|
||||
}}>
|
||||
Map Controls
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
{/* Search Form */}
|
||||
<div className="search-container" style={{
|
||||
background: 'linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%)',
|
||||
padding: '20px',
|
||||
borderRadius: '16px',
|
||||
marginBottom: '24px',
|
||||
border: '1px solid #e9ecef',
|
||||
boxShadow: '0 2px 8px rgba(0,0,0,0.04)'
|
||||
}}>
|
||||
<form onSubmit={submitForm}>
|
||||
<input
|
||||
value={term}
|
||||
onChange={(e) => setTerm(e.target.value)}
|
||||
type="text"
|
||||
placeholder="Search for any location..."
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '14px 16px',
|
||||
border: '1px solid #dee2e6',
|
||||
borderRadius: '12px',
|
||||
marginBottom: '12px',
|
||||
fontSize: '14px',
|
||||
fontFamily: "'Poppins', sans-serif",
|
||||
backgroundColor: 'white',
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.04)',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
boxSizing: 'border-box',
|
||||
outline: 'none'
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '14px',
|
||||
background: 'linear-gradient(135deg, #2c3e50 0%, #34495e 100%)',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '12px',
|
||||
cursor: 'pointer',
|
||||
fontSize: '14px',
|
||||
fontWeight: '600',
|
||||
fontFamily: "'Poppins', sans-serif",
|
||||
boxShadow: '0 4px 12px rgba(44, 62, 80, 0.2)',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)'
|
||||
}}
|
||||
>
|
||||
🔍 Search Location
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{/* Layer Toggle List */}
|
||||
<div>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '10px 0',
|
||||
borderBottom: '1px solid #eee'
|
||||
marginBottom: '16px'
|
||||
}}>
|
||||
<span style={{
|
||||
fontSize: '13px',
|
||||
color: '#333',
|
||||
flex: 1,
|
||||
marginRight: '10px'
|
||||
<h4 style={{
|
||||
margin: '0',
|
||||
color: '#495057',
|
||||
fontSize: '16px',
|
||||
fontWeight: '600'
|
||||
}}>
|
||||
{formatLayerName(layer.topic)}
|
||||
Data Layers
|
||||
</h4>
|
||||
<span style={{
|
||||
background: 'linear-gradient(135deg, #e9ecef 0%, #f8f9fa 100%)',
|
||||
color: '#6c757d',
|
||||
padding: '4px 8px',
|
||||
borderRadius: '12px',
|
||||
fontSize: '12px',
|
||||
fontWeight: '500',
|
||||
boxShadow: '0 1px 3px rgba(0,0,0,0.05)'
|
||||
}}>
|
||||
{layerConfigs.length}
|
||||
</span>
|
||||
|
||||
{searchCompleted && (
|
||||
<label style={{
|
||||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
width: '44px',
|
||||
height: '24px'
|
||||
</div>
|
||||
|
||||
{layerConfigs.map((layer, _index) => (
|
||||
<div key={layer.topic} style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: '16px',
|
||||
marginBottom: '8px',
|
||||
background: layerVisibility[layer.topic]
|
||||
? 'linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%)'
|
||||
: 'white',
|
||||
border: `1px solid ${layerVisibility[layer.topic] ? '#2c3e50' : '#e9ecef'}`,
|
||||
borderRadius: '12px',
|
||||
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
boxShadow: layerVisibility[layer.topic]
|
||||
? '0 4px 8px rgba(44, 62, 80, 0.1)'
|
||||
: '0 1px 3px rgba(0,0,0,0.05)',
|
||||
cursor: 'pointer'
|
||||
}}>
|
||||
<span style={{
|
||||
fontSize: '14px',
|
||||
color: '#2c3e50',
|
||||
flex: 1,
|
||||
marginRight: '12px',
|
||||
fontWeight: '500'
|
||||
}}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={layerVisibility[layer.topic] || false}
|
||||
onChange={() => toggleLayer(layer.topic)}
|
||||
style={{ opacity: 0, width: 0, height: 0 }}
|
||||
/>
|
||||
<span style={{
|
||||
position: 'absolute',
|
||||
cursor: 'pointer',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: layerVisibility[layer.topic] ? '#007bff' : '#ccc',
|
||||
borderRadius: '24px',
|
||||
transition: '0.3s',
|
||||
display: 'flex',
|
||||
alignItems: 'center'
|
||||
{formatLayerName(layer.topic)}
|
||||
</span>
|
||||
|
||||
{searchCompleted && (
|
||||
<label style={{
|
||||
position: 'relative',
|
||||
display: 'inline-block',
|
||||
width: '48px',
|
||||
height: '26px'
|
||||
}}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={layerVisibility[layer.topic] || false}
|
||||
onChange={() => toggleLayer(layer.topic)}
|
||||
style={{ opacity: 0, width: 0, height: 0 }}
|
||||
/>
|
||||
<span style={{
|
||||
position: 'absolute',
|
||||
content: '',
|
||||
height: '18px',
|
||||
width: '18px',
|
||||
left: layerVisibility[layer.topic] ? '23px' : '3px',
|
||||
bottom: '3px',
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '50%',
|
||||
transition: '0.3s',
|
||||
boxShadow: '0 2px 4px rgba(0,0,0,0.2)'
|
||||
}} />
|
||||
cursor: 'pointer',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
background: layerVisibility[layer.topic]
|
||||
? 'linear-gradient(135deg, #2c3e50 0%, #34495e 100%)'
|
||||
: '#dee2e6',
|
||||
borderRadius: '26px',
|
||||
transition: '0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
boxShadow: 'inset 0 1px 3px rgba(0,0,0,0.1)'
|
||||
}}>
|
||||
<span style={{
|
||||
position: 'absolute',
|
||||
content: '',
|
||||
height: '20px',
|
||||
width: '20px',
|
||||
left: layerVisibility[layer.topic] ? '25px' : '3px',
|
||||
bottom: '3px',
|
||||
backgroundColor: 'white',
|
||||
borderRadius: '50%',
|
||||
transition: '0.3s cubic-bezier(0.4, 0, 0.2, 1)',
|
||||
boxShadow: '0 2px 6px rgba(0,0,0,0.15)'
|
||||
}} />
|
||||
</span>
|
||||
</label>
|
||||
)}
|
||||
|
||||
{!searchCompleted && (
|
||||
<span style={{
|
||||
fontSize: '12px',
|
||||
color: '#adb5bd',
|
||||
fontStyle: 'italic',
|
||||
backgroundColor: '#f8f9fa',
|
||||
padding: '4px 8px',
|
||||
borderRadius: '8px',
|
||||
boxShadow: '0 1px 2px rgba(0,0,0,0.05)'
|
||||
}}>
|
||||
Search first
|
||||
</span>
|
||||
</label>
|
||||
)}
|
||||
|
||||
{!searchCompleted && (
|
||||
<span style={{
|
||||
fontSize: '11px',
|
||||
color: '#999',
|
||||
fontStyle: 'italic'
|
||||
}}>
|
||||
Search first
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{/* Map Container */}
|
||||
<div style={{ flex: 1, position: 'relative' }}>
|
||||
<div ref={mapDivRef} style={{ width: '100%', height: '100%' }} />
|
||||
|
||||
{clickedCoordinate && (
|
||||
<div style={{
|
||||
position: 'absolute',
|
||||
bottom: '20px',
|
||||
left: '20px',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||
color: 'white',
|
||||
padding: '10px 15px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
fontFamily: 'monospace'
|
||||
}}>
|
||||
Coordinates: {clickedCoordinate[0].toFixed(2)} / {clickedCoordinate[1].toFixed(2)}
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Map Container */}
|
||||
<div className="map-container" style={{
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
backgroundColor: '#ffffff',
|
||||
}}>
|
||||
{/* Overlay for mobile when sidebar is open */}
|
||||
{isMobile && sidebarOpen && (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||||
zIndex: 999,
|
||||
transition: 'opacity 0.3s ease'
|
||||
}}
|
||||
onClick={() => setSidebarOpen(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div ref={mapDivRef} style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: '0',
|
||||
overflow: 'hidden'
|
||||
}} />
|
||||
|
||||
{/* Coordinate Display */}
|
||||
{clickedCoordinate && (
|
||||
<div className="coordinate-display" style={{
|
||||
position: 'absolute',
|
||||
bottom: '24px',
|
||||
left: '24px',
|
||||
background: 'rgba(44, 62, 80, 0.9)',
|
||||
color: 'white',
|
||||
padding: '12px 16px',
|
||||
borderRadius: '12px',
|
||||
fontSize: '13px',
|
||||
fontFamily: "'Poppins', monospace",
|
||||
fontWeight: '500',
|
||||
boxShadow: '0 8px 32px rgba(44, 62, 80, 0.3)',
|
||||
backdropFilter: 'blur(10px)',
|
||||
border: '1px solid rgba(255, 255, 255, 0.1)',
|
||||
animation: 'fadeInUp 0.3s ease-out'
|
||||
}}>
|
||||
📍 Coordinates: {clickedCoordinate[0].toFixed(4)}, {clickedCoordinate[1].toFixed(4)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default OpenLayersMap;
|
||||
Loading…
Reference in a new issue