npm Pakete overlapping-marker-spiderfier-leaflet und leaflet.smooth_marker_bouncing benutzt
This commit is contained in:
@@ -5,88 +5,16 @@ import "leaflet/dist/leaflet.css";
|
||||
import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
|
||||
import "leaflet-contextmenu";
|
||||
import * as config from "../config/config.js";
|
||||
import dynamic from "next/dynamic";
|
||||
import "leaflet.smooth_marker_bouncing";
|
||||
//import { OverlappingMarkerSpiderfier } from "../lib/OverlappingMarkerSpiderfier.js";
|
||||
//import { OverlappingMarkerSpiderfier } from "../public/js/OverlappingMarkerSpiderfier.js";
|
||||
import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet";
|
||||
|
||||
const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||
const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
|
||||
const [map, setMap] = useState(null); // Zustand der Karteninstanz
|
||||
const [online, setOnline] = useState(navigator.onLine); // Zustand der Internetverbindung
|
||||
// Funktionen zur Überwachung der Internetverbindung
|
||||
const checkInternet = () => {
|
||||
fetch("https://tile.openstreetmap.org/1/1/1.png", { method: "HEAD" })
|
||||
.then((response) => setOnline(response.ok))
|
||||
.catch(() => setOnline(false));
|
||||
};
|
||||
|
||||
// Handle online/offline status
|
||||
useEffect(() => {
|
||||
window.addEventListener("online", checkInternet);
|
||||
window.addEventListener("offline", checkInternet);
|
||||
return () => {
|
||||
window.removeEventListener("online", checkInternet);
|
||||
window.removeEventListener("offline", checkInternet);
|
||||
};
|
||||
}, []);
|
||||
// Initialisiere die Karte
|
||||
useEffect(() => {
|
||||
if (mapRef.current && !map) {
|
||||
initialMap = L.map(mapRef.current, {
|
||||
center: [53.111111, 8.4625],
|
||||
zoom: 10,
|
||||
layers: [
|
||||
TALAS,
|
||||
ECI,
|
||||
ULAF,
|
||||
GSMModem,
|
||||
CiscoRouter,
|
||||
WAGO,
|
||||
Siemens,
|
||||
OTDR,
|
||||
WDM,
|
||||
GMA,
|
||||
Sonstige,
|
||||
TALASICL,
|
||||
],
|
||||
zoomControl: false, // Deaktiviere die Standard-Zoomsteuerung
|
||||
contextmenu: true,
|
||||
contextmenuItems: [
|
||||
{ text: "Station hinzufügen", callback: showAddStationPopup },
|
||||
{
|
||||
text: "Station öffnen (Tab)",
|
||||
icon: "img/screen_new.png",
|
||||
callback: newLink,
|
||||
},
|
||||
{
|
||||
text: "Station öffnen",
|
||||
icon: "img/screen_same.png",
|
||||
callback: sameLink,
|
||||
},
|
||||
{
|
||||
text: "Koordinaten",
|
||||
icon: "img/screen_same.png",
|
||||
callback: lata,
|
||||
},
|
||||
"-", // Divider
|
||||
{ text: "Reinzoomen", callback: zoomIn },
|
||||
{ text: "Rauszoomen", callback: zoomOut },
|
||||
{ text: "Hier zentrieren", callback: centerHere },
|
||||
],
|
||||
});
|
||||
L.tileLayer(online ? onlineTileLayer : offlineTileLayer, {
|
||||
attribution:
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||
}).addTo(initialMap);
|
||||
|
||||
if (window.OverlappingMarkerSpiderfier) {
|
||||
const oms = new window.OverlappingMarkerSpiderfier(initialMap, {
|
||||
nearbyDistance: 50,
|
||||
});
|
||||
setOms(oms);
|
||||
}
|
||||
setMap(initialMap);
|
||||
|
||||
setMap(initialMap);
|
||||
}
|
||||
}, [mapRef, map]);
|
||||
const [GisStationsStaticDistrict, setGisStationsStaticDistrict] = useState(
|
||||
[]
|
||||
); // Zustand für statische Daten
|
||||
@@ -154,65 +82,6 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||
fetchData();
|
||||
}, []); // Dependency-Array ist leer, um den Effekt nur beim Mount auszuführen
|
||||
|
||||
//------------------------------------------
|
||||
//\talas5\TileMap\img\icons\icon1.png
|
||||
// minor-marker-icon-23.png
|
||||
|
||||
// Marker hinzufügen für GisStationsStaticDistrict
|
||||
useEffect(() => {
|
||||
if (map && GisStationsStaticDistrict.length > 0) {
|
||||
// Zuerst alte Marker entfernen
|
||||
/* map.eachLayer((layer) => {
|
||||
if (layer instanceof L.Marker) {
|
||||
map.removeLayer(layer);
|
||||
}
|
||||
}); */
|
||||
|
||||
// Neue Marker für jede Station hinzufügen
|
||||
GisStationsStaticDistrict.forEach((station) => {
|
||||
const marker = L.marker([station.X, station.Y], {
|
||||
// X als Breitengrad, Y als Längengrad
|
||||
icon: L.icon({
|
||||
iconUrl: getIconPath(station.Icon),
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
shadowSize: [41, 41],
|
||||
}),
|
||||
}).addTo(map);
|
||||
|
||||
// Popup beim Überfahren mit der Maus öffnen
|
||||
marker.on("mouseover", function (e) {
|
||||
this.openPopup();
|
||||
});
|
||||
|
||||
// Popup schließen, wenn die Maus den Marker verlässt
|
||||
marker.on("mouseout", function (e) {
|
||||
this.closePopup();
|
||||
});
|
||||
// Ein Popup mit Informationen zur Station hinzufügen
|
||||
marker
|
||||
.bindPopup(`<b>${station.LD_Name}</b><br>${station.Device}`)
|
||||
.openPopup();
|
||||
marker.bindTooltip(
|
||||
`<div class="tooltip-content">${station.LD_Name}</div>`,
|
||||
{ permanent: false, direction: "top" }
|
||||
);
|
||||
// Zugriff auf das Tooltip-Element und Anwendung von Stilen
|
||||
marker.on("mouseover", () => {
|
||||
document.querySelector(".tooltip-content").style.backgroundColor =
|
||||
"#ffffff";
|
||||
document.querySelector(".tooltip-content").style.padding = "0.5rem";
|
||||
document.querySelector(".tooltip-content").style.borderRadius =
|
||||
"0.25rem";
|
||||
document.querySelector(".tooltip-content").style.border =
|
||||
"1px solid #d1d5db";
|
||||
});
|
||||
});
|
||||
}
|
||||
}, [map, GisStationsStaticDistrict]); // Abhängigkeiten hinzufügen, um sicherzustellen, dass Effekt bei Änderungen neu ausgeführt wird
|
||||
|
||||
//------------------------------------------
|
||||
//GisStationsStaticDistrict Daten laden
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
@@ -266,6 +135,7 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||
}, []); // Dependency-Array ist leer, um den Effekt nur beim Mount auszuführen
|
||||
//------------------------------------------
|
||||
//GisStationsMeasurements Daten laden
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
@@ -343,31 +213,74 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Update map layers based on online status
|
||||
// Funktionen zur Überwachung der Internetverbindung
|
||||
const checkInternet = () => {
|
||||
fetch("https://tile.openstreetmap.org/1/1/1.png", { method: "HEAD" })
|
||||
.then((response) => setOnline(response.ok))
|
||||
.catch(() => setOnline(false));
|
||||
};
|
||||
// Initialisierung der karte und hinzuügen der Layers
|
||||
useEffect(() => {
|
||||
if (map) {
|
||||
const newLayer = L.tileLayer(
|
||||
online ? onlineTileLayer : offlineTileLayer,
|
||||
{
|
||||
minZoom: 7,
|
||||
maxZoom: online ? 19 : 14,
|
||||
attribution:
|
||||
'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||
}
|
||||
);
|
||||
|
||||
map.eachLayer((layer) => {
|
||||
if (layer instanceof L.TileLayer) {
|
||||
map.removeLayer(layer);
|
||||
}
|
||||
if (mapRef.current && !map) {
|
||||
const newMap = L.map(mapRef.current, {
|
||||
center: [53.111111, 8.4625],
|
||||
zoom: 8,
|
||||
layers: [
|
||||
TALAS,
|
||||
ECI,
|
||||
ULAF,
|
||||
GSMModem,
|
||||
CiscoRouter,
|
||||
WAGO,
|
||||
Siemens,
|
||||
OTDR,
|
||||
WDM,
|
||||
GMA,
|
||||
Sonstige,
|
||||
TALASICL,
|
||||
],
|
||||
zoomControl: false, // Deaktiviere die Standard-Zoomsteuerung
|
||||
contextmenu: true,
|
||||
contextmenuItems: [
|
||||
{ text: "Station hinzufügen", callback: showAddStationPopup },
|
||||
{
|
||||
text: "Station öffnen (Tab)",
|
||||
icon: "img/screen_new.png",
|
||||
callback: newLink,
|
||||
},
|
||||
{
|
||||
text: "Station öffnen",
|
||||
icon: "img/screen_same.png",
|
||||
callback: sameLink,
|
||||
},
|
||||
{
|
||||
text: "Koordinaten",
|
||||
icon: "img/screen_same.png",
|
||||
callback: lata,
|
||||
},
|
||||
"-", // Divider
|
||||
{ text: "Reinzoomen", callback: zoomIn },
|
||||
{ text: "Rauszoomen", callback: zoomOut },
|
||||
{ text: "Hier zentrieren", callback: centerHere },
|
||||
],
|
||||
});
|
||||
|
||||
newLayer.addTo(map);
|
||||
}
|
||||
}, [online, map]);
|
||||
L.tileLayer(online ? onlineTileLayer : offlineTileLayer, {
|
||||
attribution:
|
||||
'© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||
}).addTo(newMap);
|
||||
|
||||
// Marker handling
|
||||
useEffect(() => {
|
||||
const newOms = new window.OverlappingMarkerSpiderfier(newMap, {
|
||||
nearbyDistance: 50,
|
||||
});
|
||||
|
||||
setMap(newMap);
|
||||
setOms(newOms);
|
||||
}
|
||||
}, [mapRef, map]); // Abhängigkeiten prüfen
|
||||
|
||||
// Marker hinzufügen von lokale MySQL Datenbank und nicht von APIs
|
||||
/* useEffect(() => {
|
||||
// Remove old markers
|
||||
if (map) {
|
||||
map.eachLayer((layer) => {
|
||||
@@ -410,7 +323,7 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||
marker.addTo(map);
|
||||
});
|
||||
}
|
||||
}, [map, locations, onLocationUpdate]);
|
||||
}, [map, locations, onLocationUpdate]); */
|
||||
|
||||
//------------------------------------------
|
||||
function parsePoint(pointString) {
|
||||
@@ -557,22 +470,6 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||
L.DomEvent.on(popupContent, "submit", handleSubmit);
|
||||
};
|
||||
|
||||
/*
|
||||
const handleSubmit = (event) => {
|
||||
event.preventDefault();
|
||||
const form = event.target;
|
||||
const data = {
|
||||
name: form.name.value,
|
||||
type: form.type.value,
|
||||
latitude: form.lat.value,
|
||||
longitude: form.lng.value,
|
||||
};
|
||||
|
||||
onAddLocation(name, type, lat, lng);
|
||||
console.log("Name: ", name, "Type: ", type, "Lat: ", lat, "Lng: ", lng);
|
||||
map.closePopup();
|
||||
};
|
||||
*/
|
||||
// Funktion zum Hinzufügen eines neuen Standorts
|
||||
async function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
@@ -615,138 +512,123 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||
var y = 7.739617925303934;
|
||||
var zoom = 7;
|
||||
|
||||
/* for (var i = 0; i < GisStationsStaticDistrictlength; i++) {
|
||||
var gisStatics = GisStationsStaticDistrict[i];
|
||||
if (stationValue === gisStatics.Area_Name) {
|
||||
//console.log(gisStatics.X+","+gisStatics.Y);
|
||||
x = gisStatics.X;
|
||||
y = gisStatics.Y;
|
||||
initialMap.flyTo([x, y], zoom);
|
||||
}
|
||||
|
||||
function getIconPath(status, iconNumber, marker) {
|
||||
let path = status
|
||||
? `TileMap/img/icons/${status}-marker-icon-${iconNumber}.png`
|
||||
: `TileMap/img/icons/marker-icon-${iconNumber}.png`;
|
||||
|
||||
// Wenn der Pfad das Wort "critical" enthält, dann den Marker bouncing options setzen
|
||||
if (path.includes("critical")) {
|
||||
// Setze Bouncing-Optionen
|
||||
marker.setBouncingOptions({
|
||||
bounceHeight: 15, // Höhe des Bounces
|
||||
contractHeight: 12, // Höhe des Einzugs beim Landen
|
||||
bounceSpeed: 52, // Geschwindigkeit des Bounces
|
||||
contractSpeed: 52, // Geschwindigkeit des Einzugs
|
||||
shadowAngle: null, // Standard-Schattenwinkel
|
||||
});
|
||||
// Check if the icon path includes 'critical'
|
||||
if (path.includes("critical")) {
|
||||
// marker.bounce(3);
|
||||
}
|
||||
}
|
||||
if (y === 7.739617925303934) {
|
||||
zoom = 8;
|
||||
} */
|
||||
initialMap.flyTo([x, y], zoom);
|
||||
|
||||
/* var popup = new L.Popup();
|
||||
oms.addListener("click", function (marker) {
|
||||
popup.setContent(marker.desc);
|
||||
popup.setLatLng(marker.getLatLng());
|
||||
map.openPopup(popup);
|
||||
});
|
||||
|
||||
for (var i = 0; i < window.mapData.length; i++) {
|
||||
var datum = window.mapData[i];
|
||||
var loc = new L.LatLng(datum.lat, datum.lon);
|
||||
var marker = new L.Marker(loc);
|
||||
marker.desc = datum.d;
|
||||
map.addLayer(marker);
|
||||
//oms.addMarker(marker); // <-- here
|
||||
} */
|
||||
|
||||
//-------------------------------------
|
||||
return path;
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//Informationen in Tooltips einfügen
|
||||
//\talas5\TileMap\img\icons\icon1.png
|
||||
// minor-marker-icon-23.png
|
||||
|
||||
// Marker hinzufügen für GisStationsStaticDistrict
|
||||
useEffect(() => {
|
||||
if (map && oms && GisStationsStaticDistrict.length > 0) {
|
||||
map.eachLayer((layer) => {
|
||||
if (layer instanceof L.Marker) {
|
||||
map.removeLayer(layer);
|
||||
}
|
||||
});
|
||||
// Stellen Sie sicher, dass sowohl `map` als auch `oms` initialisiert sind
|
||||
if (!map || !oms) {
|
||||
console.error("Map or OMS is not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
GisStationsStaticDistrict.forEach((station) => {
|
||||
// Filtere alle Statusobjekte für diese station.Na
|
||||
const statusObjects = GisStationsStatusDistrict.filter(
|
||||
(status) => status.IdLD === station.IdLD
|
||||
);
|
||||
// Alte Marker entfernen, indem alle Marker, die durch OMS verwaltet werden, gelöscht werden
|
||||
oms.clearMarkers();
|
||||
map.eachLayer((layer) => {
|
||||
if (layer instanceof L.Marker) {
|
||||
map.removeLayer(layer);
|
||||
}
|
||||
});
|
||||
|
||||
// Alle Status-Objekte mit gleicher IdLD finden
|
||||
const matchingStatuses = GisStationsStatusDistrict.filter(
|
||||
(status) => status.IdLD === station.IdLD
|
||||
);
|
||||
let status2 = "";
|
||||
let statusInfo = "";
|
||||
// Neue Marker für jede Station hinzufügen
|
||||
GisStationsStaticDistrict.forEach((station) => {
|
||||
// Filter für Statusobjekte dieser spezifischen Station
|
||||
const matchingStatuses = GisStationsStatusDistrict.filter(
|
||||
(status) => status.IdLD === station.IdLD
|
||||
);
|
||||
|
||||
// Umdrehen der Reihenfolge der Statusmeldungen
|
||||
matchingStatuses.reverse().forEach((status) => {
|
||||
statusInfo += `
|
||||
<div class="flex items-center my-1">
|
||||
<div class="w-2 h-2 mr-2 inline-block rounded-full" style="background-color: ${status.Co};"></div>
|
||||
${status.Me} <span style="color: ${status.Co};">(${status.Na})</span>
|
||||
</div>`;
|
||||
const marker = L.marker([station.X, station.Y], {
|
||||
icon: L.icon({
|
||||
iconUrl: "default-icon.png", // Default, wird geändert
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
shadowSize: [41, 41],
|
||||
}),
|
||||
}).addTo(map);
|
||||
|
||||
status2 = status.Na;
|
||||
});
|
||||
|
||||
let iconPath = getIconPath(status2, station.Icon);
|
||||
|
||||
const marker = L.marker([station.X, station.Y], {
|
||||
icon: L.icon({
|
||||
iconUrl: iconPath,
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
shadowSize: [41, 41],
|
||||
}),
|
||||
});
|
||||
|
||||
marker.addTo(map);
|
||||
oms.addMarker(marker); // Add marker to the OverlappingMarkerSpiderfier instance
|
||||
marker.on("mouseover", function (e) {
|
||||
this.openPopup();
|
||||
});
|
||||
|
||||
marker.on("mouseout", function (e) {
|
||||
this.closePopup();
|
||||
});
|
||||
// String-Zusammenstellung für das Popup-Infofenster
|
||||
let statusInfo = matchingStatuses
|
||||
.reverse()
|
||||
.map(
|
||||
(status) => `
|
||||
<div class="flex items-center my-1">
|
||||
<div class="w-2 h-2 mr-2 inline-block rounded-full" style="background-color: ${status.Co};"></div>
|
||||
${status.Me} <span style="color: ${status.Co};">(${status.Na})</span>
|
||||
</div>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
|
||||
// Bestimmen des Icons basierend auf dem Status
|
||||
let iconPath = getIconPath(
|
||||
matchingStatuses[0]?.Na || "",
|
||||
station.Icon,
|
||||
marker
|
||||
.bindPopup(
|
||||
`<b>${station.LD_Name}</b><br>${station.Device}<br>${station.Area_Short} (${station.Area_Name})<br>${station.Location_Short} (${station.Location_Name}) <br>${statusInfo}<br><br>`
|
||||
)
|
||||
.openPopup();
|
||||
});
|
||||
}
|
||||
}, [map, GisStationsStaticDistrict, oms, GisStationsStatusDistrict]); // Include GisStationsStatusDistrict in dependencies
|
||||
);
|
||||
|
||||
marker.setIcon(
|
||||
L.icon({
|
||||
iconUrl: iconPath,
|
||||
iconSize: [25, 41],
|
||||
iconAnchor: [12, 41],
|
||||
popupAnchor: [1, -34],
|
||||
shadowSize: [41, 41],
|
||||
})
|
||||
);
|
||||
// Check if the icon path includes 'critical' and initiate bouncing
|
||||
if (iconPath.includes("critical")) {
|
||||
marker.setBouncingOptions({
|
||||
bounceHeight: 15,
|
||||
contractHeight: 12,
|
||||
bounceSpeed: 52,
|
||||
contractSpeed: 52,
|
||||
shadowAngle: null,
|
||||
});
|
||||
marker.bounce(3);
|
||||
}
|
||||
// Marker zu OMS und der Karte hinzufügen
|
||||
oms.addMarker(marker);
|
||||
marker.addTo(map).bindPopup(`
|
||||
<b>${station.LD_Name}</b><br>
|
||||
${station.Device}<br>
|
||||
${station.Area_Short} (${station.Area_Name})<br>
|
||||
${station.Location_Short} (${station.Location_Name})<br>
|
||||
${statusInfo}<br>
|
||||
`);
|
||||
});
|
||||
}, [map, oms, GisStationsStaticDistrict, GisStationsStatusDistrict]);
|
||||
|
||||
//------------------------------------------
|
||||
// Funktion, die den Pfad zum entsprechenden Icon basierend auf dem Status generiert
|
||||
/* function getIconPath(status, iconId) {
|
||||
let prefix = "";
|
||||
switch (status) {
|
||||
case "critical":
|
||||
prefix = "critical-marker-icon";
|
||||
break;
|
||||
case "major":
|
||||
prefix = "major-marker-icon";
|
||||
break;
|
||||
case "minor":
|
||||
prefix = "minor-marker-icon";
|
||||
break;
|
||||
case "system":
|
||||
prefix = "system-marker-icon";
|
||||
break;
|
||||
case "ok":
|
||||
default:
|
||||
prefix = "marker-icon"; // Annahme: "ok" ist der Standardstatus und grün
|
||||
break;
|
||||
}
|
||||
return `path/to/icons/${prefix}-${iconId}.png`;
|
||||
} */
|
||||
//------------------------------------------
|
||||
function getIconPath(status, iconNumber) {
|
||||
if (status) {
|
||||
// Wenn status vorhanden ist, füge ihn in den Pfad ein mit Bindestrich
|
||||
|
||||
return `TileMap/img/icons/${status}-marker-icon-${iconNumber}.png`;
|
||||
} else {
|
||||
// Wenn kein status vorhanden ist, lasse den Status-Teil ganz weg
|
||||
return `TileMap/img/icons/marker-icon-${iconNumber}.png`;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user