Search code examples
javascriptleaflet

The centers of the arrow tails on my Leaflet markers are misaligned


I'm using Leaflet to add markers with arrows, but the centers of the arrow tails are not aligned properly. How can I fix this alignment issue? leaflet version is leaflet@1.7.1 I have multiple pairs of arrows as markers in the leaflet which I am rotating dynamically but the pair's centers is not aligning . Here's the icon code

arrowIconGreen = L.icon({
    iconUrl: '../../content/images/right-arrow-green.png',
    shadowUrl: '',
    iconSize: [33, 35], // size of the icon
    shadowSize: [0, 0], // size of the shadow
    iconAnchor: [16, 35], // point of the icon which will correspond to marker's location
    shadowAnchor: [4, 62], // the same for the shadow
    popupAnchor: [0, -10] // point from which the popup should open relative to the iconAnchor
});
arrowIconBrown = L.icon({
    iconUrl: '../../content/images/right-arrow-light-brown.png',
    shadowUrl: '',
    iconSize: [33, 35], // size of the icon
    shadowSize: [0, 0], // size of the shadow
    iconAnchor: [16, 35], // point of the icon which will correspond to marker's location
    shadowAnchor: [4, 62], // the same for the shadow
    popupAnchor: [0, -10] // point from which the popup should open relative to the iconAnchor
});
const nacellePositionCloseView = L.marker(new L.LatLng(marker.lat, marker.lng), {
    draggable: false,
    dragging: false,
    autoPan: false,
    icon: arrowIconBrown
}).addTo(satelliteMap)
nacellePositionCloseView.setRotationAngle(360 - Number(nacelleDegree.value));
nacellePositionCloseView.setRotationOrigin("center center");
const windDirectionCloseView = L.marker(new L.LatLng(marker.lat, marker.lng), {
    draggable: false,
    dragging: false,
    autoPan: false,
    icon: arrowIconGreen
}).addTo(satelliteMap)
windDirectionCloseView.setRotationAngle(360 - Number(windDegree.value));
windDirectionCloseView.setRotationOrigin("center center");

Here's the picture:

as you can see the tails of the arrows are not concurrent

I want the tails of the two arrows to be concurrent. Their browser css properties are also same except the rotation angle. Please help.


Solution

  • (This answers assumes that you are using Leaflet.RotatedMarker.)

    Your arrows origin is centred on the left and therefore you need to use center left instead of center center for the rotation origin:

    nacellePositionCloseView.setRotationOrigin("center left");
    

    Side note: Leaflet.RotatedMarker's implementation is using the CSS property transform-origin. You can also use pixel values if needed, for example if the horizontal arrow line is not centered within the icon image.

    Here is a working example (replace the values for greenArrowImagePath and brownArrowImagePath; and note that I am using arbitrary values for the rotation angles):

    <!DOCTYPE html>
    <html lang="en">
    <head>
        
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>StackOverflow Question 79005640</title>
    
        <link rel="stylesheet" href="leaflet.css" />
        <script src="leaflet.js"></script>
    
        <script src="leaflet.rotatedMarker.js">
        </script>
    
        <style>
            body {
                margin: 0;
            }
            #map { 
                height: 100vh;
            }
            .reference-marker .circle {
                background-color: #f07819;
                border-radius: 50%;
                height: 20px; width: 20px;
            }
        </style>
    
    </head>
    <body>
        
        <div id="map"></div>
    
        <script>
            
            const coordinate = [46.43283, 9.76596];
    
            const map = L.map('map').setView(coordinate, 13);
    
            L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 19,
                // add link to attribution, omitted in this code example
                // due to width limit, i.e., avoid horizontal scrolling
                attribution: '&copy; OpenStreetMap',
            }).addTo(map);
    
            const brownArrowImagePath = 'right-arrow-light-brown@8x.png';
            const greenArrowImagePath = 'right-arrow-green@8x.png';
    
            const referenceMarker = L.marker(new L.LatLng(...coordinate), {
                icon: L.divIcon({
                    className: 'reference-marker',
                    iconSize: [20, 20],
                    html: '<div class="circle"></div>',
                }),
            }).addTo(map);
    
            const nacellePositionMarker = L.marker(new L.LatLng(...coordinate), {
                icon: L.icon({
                    iconUrl: brownArrowImagePath,
                    iconSize: [80, 20],
                    iconAnchor: [0, 10],
                }),
            }).addTo(map);
    
            nacellePositionMarker.setRotationAngle(360 - 42);  // arbitrary value
            nacellePositionMarker.setRotationOrigin("center left");
            
            const windDirectionMarker = L.marker(new L.LatLng(...coordinate), {
                icon: L.icon({
                    iconUrl: greenArrowImagePath,
                    iconSize: [80, 20],
                    iconAnchor: [0, 10],
                }),
            }).addTo(map);
    
            windDirectionMarker.setRotationAngle(360 + 84);  // arbitrary value
            windDirectionMarker.setRotationOrigin("center left");
    
        </script>
    
    </body>
    </html>
    

    enter image description here

    I also uploaded the code to a GitHub repository here and a demo can be found here.