2

I am using Leaflet.js to make a timeline-based playback of marker locations, using a Leaflet Playback listed on Leaflet Plugins.

I am defining an L.divIcon earlier in my code:

var busIcon = L.divIcon({className: 'bus-div-icon', html:"1"});

And later on I have to pass it to the plugin's function:

var playbackOptions = {
  //...
  marker: {
    icon : busIcon,
    getPopup: function(featureData) {
      // returns something using featureData.properties.name, so here a function works
    }
  },
  //...

I want to populate the html variable in the divIcon dynamically, similarly to how getPopup has been defined (this code I have copied and customized from the plugin's documentation example).

But when I try to pass a function to the icon:

icon: function(featureData) {
  return L.divIcon({className: 'bus-div-icon', html: 
  featureData.properties.busnum });
},

It did not work; I got this error in my console:

Uncaught TypeError: t.icon.createIcon is not a function at e._initIcon (leaflet.js:5) at e.onAdd (leaflet.js:5) at e._layerAdd (leaflet.js:5) at e.whenReady (leaflet.js:5) at e.addLayer (leaflet.js:5) at e.addTo (leaflet.js:5) at e.addTrack (LeafletPlayback.min.js:1) at e.addData (LeafletPlayback.min.js:1) at e.setData (LeafletPlayback.min.js:1) at e.initialize (LeafletPlayback.min.js:1)

I tried another strategy, and no errors this time:

icon: L.divIcon({
  className: 'bus-div-icon',
  html: function(featureData) {
    console.log("Hello!");
    return '1';
  }
}),

.. but the results were hilarious!

Imgur

What happened here is that instead of executing the function, it has displayed that whole code as text on the map! See screenshot above.

How to populate html dynamically?

1

The beauty of Leaflet is that can "easily" customize the behaviour of its classes, including for plugins which follow Leaflet classes conventions.

Therefore you can customize how LeafletPlayback plugin creates its MoveableMarker, so that it uses a new "getIcon" function that you would pass in the options, similarly to the getPopup option that you mention:

L.Playback.MoveableMarker.include({
  _originalInitialize: L.Playback.MoveableMarker.prototype.initialize,
  initialize: function(startLatLng, options, feature) {
    // Perform some operations before doing the normal initialization.
    var marker_options = options.marker || {};

    // "Dynamically" assign the icon.
    if (marker_options.getIcon) {
      marker_options.icon = marker_options.getIcon(feature);
    }

    // Now perform the normal initialization.
    this._originalInitialize.call(this, startLatLng, options, feature);
  }
});

Now you can pass marker.getIcon option to new L.Playback, which will receive the feature data as parameter, so that you can build your icon accordingly.

Example based on the plugin example 0: https://plnkr.co/edit/8GQHHfzE9qkvPEb20pGn?p=preview

EDIT: changed marker_options.getIcon(this.feature); to marker_options.getIcon(feature); as that's the one carrying the feature data.

  • hi @ghybs, the plnkr link is down, FYI. I was getting stuck with getIcon: function(featureData) {..} : the featureData was coming as invalid. Then I looked at the original LeafletPlayback.js and found that we have to pass feature to getIcon in your code snippet, not this.feature. Now it works! – Nikhil VJ Jun 16 '18 at 10:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.