Files
Brancheneinstufung2/heatmap-tool/frontend/src/components/MapDisplay.tsx
Floke a3cec85798 [2fd88f42] 1. Kartendarstellung (Neutralisierung):
1. Kartendarstellung (Neutralisierung):
       * Die TileLayer-URL in heatmap-tool/frontend/src/components/MapDisplay.tsx wurde auf eine neutrale CARTO light_all-Kachelansicht umgestellt und die Quellenangabe entsprechend angepasst.
2026-02-11 15:36:06 +00:00

99 lines
3.2 KiB
TypeScript

// src/components/MapDisplay.tsx
import React from 'react';
import { MapContainer, TileLayer, CircleMarker, Tooltip } from 'react-leaflet';
import { HeatmapLayer } from 'react-leaflet-heatmap-layer-v3';
import 'leaflet/dist/leaflet.css';
import 'leaflet.heat';
import MarkerClusterGroup from 'react-leaflet-cluster';
import type { HeatmapPoint, MapMode, TooltipColumn } from '../App';
interface MapDisplayProps {
heatmapData: HeatmapPoint[];
radiusMultiplier: number;
viewMode: MapMode;
tooltipColumns: TooltipColumn[];
}
const MapDisplay: React.FC<MapDisplayProps> = ({ heatmapData, radiusMultiplier, viewMode, tooltipColumns }) => {
const germanyCenter: [number, number] = [51.1657, 10.4515];
const maxCount = Math.max(...heatmapData.map(p => p.count), 1);
const calculateRadius = (count: number) => {
return 3 + Math.log(count + 1) * 5 * radiusMultiplier;
};
const getColor = (count: number) => {
const ratio = count / maxCount;
if (ratio > 0.8) return '#d73027'; // Red
if (ratio > 0.5) return '#fdae61'; // Orange
if (ratio > 0.2) return '#fee08b'; // Yellow
return '#66bd63'; // Green
};
const renderPoints = () => (
<MarkerClusterGroup>
{heatmapData.map((point, idx) => (
<CircleMarker
key={idx}
center={[point.lat, point.lon]}
radius={calculateRadius(point.count)}
pathOptions={{
color: getColor(point.count),
fillColor: getColor(point.count),
fillOpacity: 0.7
}}
>
<Tooltip>
PLZ: {point.plz} <br />
Count: {point.count}
{tooltipColumns.map(col => {
if (col.visible && point.attributes_summary && point.attributes_summary[col.name]) {
const values = point.attributes_summary[col.name];
return (
<div key={col.id}>
<strong>{col.name}:</strong> {Array.isArray(values) ? values.join(', ') : values}
</div>
);
}
return null;
})}
</Tooltip>
</CircleMarker>
))}
</MarkerClusterGroup>
);
const renderHeatmap = () => (
<HeatmapLayer
points={heatmapData}
longitudeExtractor={(p: HeatmapPoint) => p.lon}
latitudeExtractor={(p: HeatmapPoint) => p.lat}
intensityExtractor={(p: HeatmapPoint) => p.count}
radius={25}
blur={20}
max={maxCount * 0.1} // Adjust max intensity for better visualization
/>
);
if (heatmapData.length === 0) {
return (
<div>
<p>No data to display on the map.</p>
<p>Upload a file and apply filters to see the heatmap.</p>
</div>
);
}
return (
<MapContainer key={viewMode} center={germanyCenter} zoom={6} style={{ height: '100%', width: '100%' }}>
<TileLayer
url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png"
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>'
/>
{viewMode === 'points' ? renderPoints() : renderHeatmap()}
</MapContainer>
);
};
export default MapDisplay;