Mateusz Gnys
Mateusz Gnys

Reputation: 19

Leaflet map: marker's smooth transition opacity change

I want to achieve effect of smooth transition while mouse hovers over. Same (similar) as the popup does. I've got it covered by now with following code:

var i, j, k = 0;
var opaOn = 0.5;
var opaOff = 1.0;
var waitInterval=20;
    var marker1 = L.marker([54.351194, 18.644001], {
        title: "F-25",
        opacity: opaOn
      })
      .addTo(map)
      .on('mouseover', function(e) {
        localName = 'Marker 1';
        popupName.setContent(localName);
        this.openPopup();
        for (let i = 1; i <= (1.0 - opaOn) * 10; i++) {
          setTimeout(function timer() {
            j = ((i / 10) + opaOn);
            marker1.setOpacity(j);
            popupMaster.setContent("Value: " + j);
          }, i * waitInterval);
        }

      })
      .on('mouseout', function(e) {
        this.closePopup();

        for (let i = 1; i <= (j - opaOn) * 10; i++) {
          setTimeout(function timer() {
            k = (opaOff - (i / 10));
            marker1.setOpacity(k);
            popupMaster.setContent("Value: " + k);
          }, i * waitInterval);
        }


      })
      .on('click', function(e) {
        popupMaster.setContent('hello');
      })
      .bindPopup(popupName);

This is some of the versions I've tried before, it is kinda messy but the idea is that it adds 0.1 opacity every 20ms(waitInterval) from 0.5 (opaOn) to 1.0 (opaOff) while 'mouseover', and doing backward operation while 'mouseout'.

Problem is that when mouse crosses through marker quickly, opacity messes up. I do know why it happens, as 'mouseover' loop didn't manage to finish before 'mouseout' starts, so 'mouseover' still adds value while 'mouseout' tries to substract it. I've tried to add boolean trigger and if condition that one cannot get executed if another didn't finish. I've tried to add setTimeout() for 'mouseout' so that it automatically waits some time then starts to do its substraction - no luck. I've tried some more different variation, but there always was that small gap allowing for the 'script' to crash.

I've read about asynchronous functions/events, but I wasn't able to implement it anyhow to my project.

Every little helps guys, thanks in advance!

My project in fiddle

Upvotes: 1

Views: 1857

Answers (1)

nikoshr
nikoshr

Reputation: 33344

If your goal is just to add a transition on opacity, you probably should use CSS transitions.

With these CSS classes

.leaflet-marker-icon {
    opacity: 0.5;
}
.leaflet-marker-hover {
    transition-property: opacity;
    transition-duration: 1s;
    opacity: 1;
}

toggle a leaflet-marker-hover class on mouseover/mouseout

L.marker([54.351194, 18.644001], {
    title: "F-25"
})
.addTo(map)
.on('mouseover', function(e) {
    popupName.setContent('Marker 1');
    this.openPopup();
    L.DomUtil.addClass(e.target.getElement(), 'leaflet-marker-hover');
})
.on('mouseout', function(e) {
    this.closePopup();
    L.DomUtil.removeClass(e.target.getElement(), 'leaflet-marker-hover');
})
.bindPopup(popupName);

And a demo based on your example

var center = [54.351194, 18.644001];
var map = L.map('map').setView(center, 11);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 40
}).addTo(map);

var popupName = L.popup({
    closeOnClick: false,
    autoClose: false,
    closeButton: false
});


var points = [
    {latlng: [54.351194, 18.644001], title: "F-25", name: "Marker 1"},
    {latlng: [54.361194, 18.664001], title: "F-26", name: "Marker 2"},
]

points.forEach(function(p) {
    L.marker(p.latlng, {
        title: p.title
    })
    .addTo(map)
    .on('mouseover', function(e) {
        popupName.setContent(p.name);
        this.openPopup();
        L.DomUtil.addClass(e.target.getElement(), 'leaflet-marker-hover');
    })
    .on('mouseout', function(e) {
        this.closePopup();
        L.DomUtil.removeClass(e.target.getElement(), 'leaflet-marker-hover');
    })
    .bindPopup(popupName);
});
html, body, #map {
  height: 100%;
}

.leaflet-marker-icon {
  opacity: 0.5;
}

.leaflet-marker-hover {
  transition-property: opacity;
  transition-duration: 1s;
  opacity: 1;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />

<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>

<div id="map"></div>

Upvotes: 1

Related Questions