console.log("map js init") var map; var no_cluster; var marker_cluster; var secondMarkerGroup; var mbounds = []; var markers = []; var dataload = 0; function lzw_decode(s) { var data = (s + "").split(" "); var out = []; var phrase; console.log("lzw decode"); console.log(data.length); for (var i = 1; i < data.length; i++) { phrase = String.fromCharCode(data[i]); out.push(phrase); } return out.join(""); } function decluster() { console.log("decl"); map.removeLayer(marker_cluster); map.addLayer(no_cluster); console.log(mbounds); var br = L.featureGroup(mbounds).getBounds(); console.log(br); //map.fitBounds(br); //alert(map.getZoom()); setTimeout(()=>{ logOverlappingMarkers(); },1000); } function extendBounds(bounds) { setTimeout(()=>{ console.log(logOverlappingMarkers()); },100) //ensure markers have a bit of padding so they dont get cut off on egde of map div bounds._northEast.lat=bounds._northEast.lat + 0.0008; bounds._northEast.lng=bounds._northEast.lng + 0.0008; bounds._southWest.lat=bounds._southWest.lat - 0.0008; bounds._southWest.lng=bounds._southWest.lng - 0.0008; return bounds; } function logOverlappingMarkers() { // Get all elements with class "leaflet-marker-icon" var markerElements = document.querySelectorAll('.leaflet-marker-icon.leaflet-div-icon'); // Filter only the marker elements var markers = Array.from(markerElements).filter(function(element) { return element.classList.contains('leaflet-marker-icon'); }); // Call the function to determine overlapping markers var overlappingMarkers = areMarkersOverlapping(markers); // Log the overlapping markers overlappingMarkers.forEach(function(marker) { console.log(marker); }); } function areMarkersOverlapping(markers) { console.log("\n\n\n\n\n\n\n\n\n\n\n",markers,"\n\n\n\n\n\n\n\n\n\n\n") var overlappingMarkers = []; // Iterate over each marker markers.forEach(function(marker1, index1) { // Extract the translate3d value from the marker's style var translateValue1 = marker1.style.transform; var coordinates1 = extractCoordinatesFromTranslate(translateValue1); //console.log(marker1,coordinates1) for (var index2 = index1 + 1; index2 < markers.length; index2++) { var marker2 = markers[index2]; var translateValue2 = marker2.style.transform; var coordinates2 = extractCoordinatesFromTranslate(translateValue2); //console.log(marker2,coordinates2) // Calculate the distance between the markers based on their coordinates var distance = calculateDistance(coordinates1, coordinates2); // Set a threshold value for considering markers as overlapping var threshold = 50; // Adjust as needed console.log(distance,removeLeafletStrings(marker1.className),removeLeafletStrings(marker2.className)); // Check if the distance is less than the threshold if (distance <= threshold) { overlappingMarkers.push(marker1); overlappingMarkers.push(marker2); } } }); console.log(overlappingMarkers) moveOverlappingMarkers(overlappingMarkers); return overlappingMarkers; } function moveOverlappingMarkers(overlappingMarkers) { // Iterate over each pair of overlapping markers for (var i = 0; i < overlappingMarkers.length; i += 2) { var marker1 = overlappingMarkers[i]; var marker2 = overlappingMarkers[i + 1]; // Extract the current translate3d values for both markers var translateValue1 = marker1.style.transform; var translateValue2 = marker2.style.transform; // Extract the X and Y coordinates from the translate3d values var coordinates1 = extractCoordinatesFromTranslate(translateValue1); var coordinates2 = extractCoordinatesFromTranslate(translateValue2); // Calculate the direction vector between the markers var dx = coordinates2.x - coordinates1.x; var dy = coordinates2.y - coordinates1.y; // Calculate the distance between the markers var distance = Math.sqrt(dx * dx + dy * dy); // Calculate the normalized direction vector var nx = dx / distance; var ny = dy / distance; // Calculate the move amount to separate the markers var moveAmount = calculateMoveAmount(distance); // Calculate the new positions for the markers var newX1 = coordinates1.x - nx * moveAmount; var newY1 = coordinates1.y - ny * moveAmount; var newX2 = coordinates2.x + nx * moveAmount; var newY2 = coordinates2.y + ny * moveAmount; // Update the transform property to move the markers to the new positions marker1.style.transform = 'translate3d(' + newX1 + 'px, ' + newY1 + 'px, 0)'; marker2.style.transform = 'translate3d(' + newX2 + 'px, ' + newY2 + 'px, 0)'; } } // Helper function to calculate the move amount based on the distance between markers function calculateMoveAmount(distance) { // Define a threshold distance for minimum overlap var thresholdDistance = 50; // Adjust as needed // Calculate move amount based on distance if (distance < thresholdDistance) { // Adjust the factor as needed to control the amount of movement var factor = 0.5; // Adjust as needed return (thresholdDistance - distance) * factor; } else { return 0; } } // Helper function to extract X and Y coordinates from translate3d value function extractCoordinatesFromTranslate(translateValue) { var match = translateValue.match(/translate3d\(([^,]+),([^,]+),([^,]+)/); if (match) { return { x: parseFloat(match[1]), y: parseFloat(match[2]) }; } else { return null; } } // Helper function to calculate distance between two points function calculateDistance(point1, point2) { if (point1 && point2) { var dx = point1.x - point2.x; var dy = point1.y - point2.y; return Math.sqrt(dx * dx + dy * dy); } else { return Infinity; } } function removeLeafletStrings(inputString) { const stringsToRemove = [ 'leaflet-marker-icon', 'leaflet-div-icon', 'leaflet-zoom-animated', 'leaflet-clickable', ' I', ' ' ]; const regex = new RegExp(stringsToRemove.join('|'), 'g'); return inputString.replace(regex, ''); } function recluster() { map.removeLayer(no_cluster); map.addLayer(marker_cluster); var br = L.featureGroup(mbounds).getBounds(); console.log(br); map.fitBounds(extendBounds(br)); } $(document).ready(function() { 'use strict'; $('.main-loading-inner').fadeIn(); if ($('#map-leaflet').length) { $.when($.get("/assets/map/js/cfg/?route=alberta-craft-breweries%2F")).then(function(x) { var x = (JSON.parse(x)); var param = x.zoom; map = L.map('map-leaflet', { zoom: x.zoom, maxZoom: 18, minZoom: 4, tap: false, gestureHandling: true, center: [x.lat, x.lon] }); map.on('popupopen', function(e) { //console.log(e.popup); //console.log(e.popup._source._myId) $(".map-rate.bid-" + e.popup._source._myId).html("Awaiting Rating"); loadcontenttodiv(".map-rate.bid-" + e.popup._source._myId, "/api/rating/" + e.popup._source._myId); }); map.on('moveend', function() { // This function will be called whenever the map movement ends console.log("Map movement ended"); logOverlappingMarkers(); // You can perform any actions you want here var mapBounds = map.getBounds(); var currentZoom = map.getZoom(); // Define the threshold zoom level at which you want to hide the markers var thresholdZoom = (itin_locs.length>4)?1:13; // Adjust as needed // Iterate through all markers in the secondMarkerGroup secondMarkerGroup.eachLayer(function(marker) { // Check if the marker's position is within the map bounds if (mapBounds.contains(marker.getLatLng()) && (currentZoom > thresholdZoom)) { // If the marker is within the bounds, add it to the map map.addLayer(marker); console.log("added vis") } else { // If the marker is outside the bounds, remove it from the map map.removeLayer(marker); console.log("removed non vis",mapBounds.contains(marker.getLatLng())) } }); }); map.on('zoomend', function() { // This function will be called whenever the map movement ends console.log("Map movement ended"); logOverlappingMarkers(); // You can perform any actions you want here var mapBounds = map.getBounds(); var currentZoom = map.getZoom(); // Define the threshold zoom level at which you want to hide the markers var thresholdZoom = (itin_locs.length>4)?1:13; // Adjust as needed console.log("thresholdZoom",thresholdZoom); // Iterate through all markers in the secondMarkerGroup secondMarkerGroup.eachLayer(function(marker) { // Check if the marker's position is within the map bounds console.log("zoomz",currentZoom, thresholdZoom) if (mapBounds.contains(marker.getLatLng()) && (currentZoom > thresholdZoom)) { // If the marker is within the bounds, add it to the map map.addLayer(marker); console.log("added vis") } else { // If the marker is outside the bounds, remove it from the map map.removeLayer(marker); console.log("removed non vis",mapBounds.contains(marker.getLatLng())) } }); }); marker_cluster = L.markerClusterGroup({ zIndexOffset: 1500, maxClusterRadius: function(zoom) { return (zoom <= 14) ? 45 : 1; // radius in pixels } }); no_cluster = L.featureGroup(); console.log(marker_cluster); //map.scrollWheelZoom.disable(); var OpenStreetMap_Mapnik = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { scrollWheelZoom: false, attribution: '© OpenStreetMap contributors' }).addTo(map); var mUrl = '/assets/map/js/markers/?route=alberta-craft-breweries%2F'; if (itin_locs.length > 5) { mUrl = '/assets/map/js/markers/?itin='+itin_locs; } $.get(mUrl, function(data) { //alert( "Data Loaded: " + data ); //data = lzw_decode(data); //data = JSON.parse(data); console.log(data); markers = data; $.each(markers, function(index, value) { var icon = L.divIcon({ className: "leaflet-div-icon I" + value.popname, html: '', iconSize: [50, 50], iconAnchor: [50, 50], popupAnchor: [-20, -12] }); //console.log(icon); var marker = L.marker(value.center, { icon: icon, zIndexOffset: 10000 }); //.addTo(map); marker._myId = value.popid; marker._myName = value.popname; marker.bindPopup( '
' ); //console.log(value.center); mbounds.push(L.marker(value.center)); // console.log(marker); marker_cluster.addLayer(marker); no_cluster.addLayer(marker); }); $('.main-loading-inner').fadeOut(); recluster(); }); var secondaryMarkersPane = L.DomUtil.create('div', 'leaflet-pane leaflet-secondary-markers-pane'); map.getPanes().overlayPane.appendChild(secondaryMarkersPane); secondMarkerGroup = L.featureGroup(); // Fetch markers from the second source var vUrl = '/assets/map/js/venues/?route=alberta-craft-breweries%2F'; if (itin_atrs.length > 5) { vUrl='/assets/map/js/venues/?itin='+itin_atrs; } $.get(vUrl, function(data) { // Process the data and create markers console.log(data); var secondMarkers = data; var venueorattr = (itin_locs.length>4)?"attraction":"venue"; // Adjust as needed $.each(secondMarkers, function(index, value) { var icon = L.divIcon({ className: "leaflet-div-icon-"+venueorattr+" " + value.phone + " I" + value.popname, html: '', iconSize: [25, 28], iconAnchor: [25, 25], popupAnchor: [-13, -17], zIndex:9 }); var marker = L.marker(value.center, { icon: icon, pane: secondaryMarkersPane, zIndexOffset: -1000 }); // Set any additional properties for the marker marker._myId = value.popid; marker._myName = value.popname; console.log(value); var CustomPopup = L.Popup.extend({ options: { // Define custom options here // You can specify your custom classes in the className option className: 'custom-popup' } }); var customPopup = new CustomPopup(); customPopup.setContent( '' ); // Create a custom popup instance marker.bindPopup(customPopup); // Bind a popup or other interactions as needed // ... // Add the marker to the secondMarkerGroup secondMarkerGroup.addLayer(marker); }); // Add the secondMarkerGroup to the map //map.addLayer(secondMarkerGroup); // You can also recluster if needed // recluster(); }); //fsalert(mbounds.length) //var group = L.featureGroup(mbounds).addTo(map); //map.fitBounds(group.getBounds()); //alert(group.getBounds()); }); } //console.log("/n/n/n/n"); //console.log(map); }); var lastmarker; function findAndOpenPopup(specificMarkerId) { console.log("secondMarkerGroup",secondMarkerGroup) // Function to open popup for a specific marker function openPopupForMarker(marker) { console.log(marker) lastmarker=marker; console.log("Opening popup for marker: " + marker._myId); map.setView(marker._latlng, 16); setTimeout(()=>{marker.openPopup();},250) } // Search for the specific marker ID among individual markers no_cluster.eachLayer(function(layer) { if (Number(layer._myId) === specificMarkerId || layer._myName === specificMarkerId || (layer._myId) === specificMarkerId ) { console.log("specificMarkerId",specificMarkerId); openPopupForMarker(layer); } }); // Search for the specific marker ID among markers within clusters no_cluster.eachLayer(function(layer) { if (layer.getChildCount && layer.getChildCount() > 0) { layer.getAllChildMarkers().forEach(function(child) { if (Number(child._myId) === specificMarkerId || child._myName === specificMarkerId || (child._myId) === specificMarkerId ) { openPopupForMarker(child); } }); } }); secondMarkerGroup.eachLayer(function(layer) { if (Number(layer._myId) === specificMarkerId || layer._myName === specificMarkerId || (layer._myId) === specificMarkerId ) { console.log("specificMarkerId",specificMarkerId); openPopupForMarker(layer); } }); } // Call the function to find and open the popup for a specific marker //findAndOpenPopup(specificMarkerId); // Additionally, handle cluster click event to open popup if a closed cluster is clicked marker_cluster.on('clusterclick', function(event) { event.layer.spiderfy(); // Open cluster if closed event.layer.eachLayer(function(layer) { if (layer._myId === specificMarkerId || layer._myName === specificMarkerId) { layer.openPopup(); } }); }); function xfindAndOpenPopup(specificMarkerId) { // Function to recursively search through clusters and open popup if found function searchMarkers(layer) { console.log("layer",layer); // If layer is a cluster, search through its child layers if (layer.getChildCount && layer.getChildCount() > 0) { //console.log('layer has child',layer.getChildCount()) layer.getAllChildMarkers().forEach(function(child) { searchMarkers(child); }); } else { // If layer is a marker, check if its ID matches the specificMarkerId if (layer._myId === specificMarkerId.toString() || layer._myName === specificMarkerId ) { console.warn('is marker',specificMarkerId,layer._myId, layer._myName) layer.openPopup(); return; } else { console.log('is not marker',specificMarkerId,layer._myId, layer._myName) } } } // Start the search from the top-level marker cluster group marker_cluster.eachLayer(function(layer) { searchMarkers(layer); }); marker_cluster.on('clusterclick', function(event) { event.layer.spiderfy(); // Open cluster if closed event.layer.eachLayer(function(layer) { if (layer._myId === specificMarkerId || layer._myName === specificMarkerId ) { layer.openPopup(); } }); }); } function loadcontenttodiv(div, url) { // $(div).html("Loading Content"); console.log("Load Content"); $.get(url, function(data) { console.log((data)); //data = data.replace("","") console.log(JSON.parse(data)); var objdata = JSON.parse(data); console.log(objdata.result); if (objdata.result.html) { $(div).html(objdata.result.html); console.log("Load was performed."); } else { //$(div).html(""); } }); }