80 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			80 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
(function () {
 | 
						|
    var tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
 | 
						|
    var tileAttribution = 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>';
 | 
						|
 | 
						|
    // Global export
 | 
						|
    window.deliveryMap = {
 | 
						|
        showOrUpdate: function (elementId, markers) {
 | 
						|
            var elem = document.getElementById(elementId);
 | 
						|
            if (!elem) {
 | 
						|
                throw new Error('No element with ID ' + elementId);
 | 
						|
            }
 | 
						|
 | 
						|
            // Initialize map if needed
 | 
						|
            if (!elem.map) {
 | 
						|
                elem.map = L.map(elementId);
 | 
						|
                elem.map.addedMarkers = [];
 | 
						|
                L.tileLayer(tileUrl, { attribution: tileAttribution }).addTo(elem.map);
 | 
						|
            }
 | 
						|
 | 
						|
            var map = elem.map;
 | 
						|
            if (map.addedMarkers.length !== markers.length) {
 | 
						|
                // Markers have changed, so reset
 | 
						|
                map.addedMarkers.forEach(marker => marker.removeFrom(map));
 | 
						|
                map.addedMarkers = markers.map(m => {
 | 
						|
                    return L.marker([m.y, m.x]).bindPopup(m.description).addTo(map);
 | 
						|
                });
 | 
						|
 | 
						|
                // Auto-fit the view
 | 
						|
                var markersGroup = new L.featureGroup(map.addedMarkers);
 | 
						|
                map.fitBounds(markersGroup.getBounds().pad(0.3));
 | 
						|
 | 
						|
                // Show applicable popups. Can't do this until after the view was auto-fitted.
 | 
						|
                markers.forEach((marker, index) => {
 | 
						|
                    if (marker.showPopup) {
 | 
						|
                        map.addedMarkers[index].openPopup();
 | 
						|
                    }
 | 
						|
                });
 | 
						|
            } else {
 | 
						|
                // Same number of markers, so update positions/text without changing view bounds
 | 
						|
                markers.forEach((marker, index) => {
 | 
						|
                    animateMarkerMove(
 | 
						|
                        map.addedMarkers[index].setPopupContent(marker.description),
 | 
						|
                        marker,
 | 
						|
                        4000);
 | 
						|
                });
 | 
						|
            }
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    function animateMarkerMove(marker, coords, durationMs) {
 | 
						|
        if (marker.existingAnimation) {
 | 
						|
            cancelAnimationFrame(marker.existingAnimation.callbackHandle);
 | 
						|
        }
 | 
						|
 | 
						|
        marker.existingAnimation = {
 | 
						|
            startTime: new Date(),
 | 
						|
            durationMs: durationMs,
 | 
						|
            startCoords: { x: marker.getLatLng().lng, y: marker.getLatLng().lat },
 | 
						|
            endCoords: coords,
 | 
						|
            callbackHandle: window.requestAnimationFrame(() => animateMarkerMoveFrame(marker))
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    function animateMarkerMoveFrame(marker) {
 | 
						|
        var anim = marker.existingAnimation;
 | 
						|
        var proportionCompleted = (new Date().valueOf() - anim.startTime.valueOf()) / anim.durationMs;
 | 
						|
        var coordsNow = {
 | 
						|
            x: anim.startCoords.x + (anim.endCoords.x - anim.startCoords.x) * proportionCompleted,
 | 
						|
            y: anim.startCoords.y + (anim.endCoords.y - anim.startCoords.y) * proportionCompleted
 | 
						|
        };
 | 
						|
 | 
						|
        marker.setLatLng([coordsNow.y, coordsNow.x]);
 | 
						|
 | 
						|
        if (proportionCompleted < 1) {
 | 
						|
            marker.existingAnimation.callbackHandle = window.requestAnimationFrame(
 | 
						|
                () => animateMarkerMoveFrame(marker));
 | 
						|
        }
 | 
						|
    }
 | 
						|
})();
 |