I've been liking Leaflet so far but have run into a snag. I can't get it to produce custom icons based on an attribute. Instead I get the default blue points. I've looked at several similar postings on the web but none have helped in resolving this problem. I have five hurricane icons indicating strength, and I have a switch statement in my pointToLayer function that selects the appropriate icon. In the debugger I can verify that throughout the execution of pointToLayer, all variables are defined and look reasonable. The version of Leaflet is 1.2.0. Here is my code:

    $scope.addTrackMap = function() {
      let storm_id = $scope.selected_storm.toLowerCase();

      url = '/geoserver/proxy.cfm?service=wfs&version=2.11.2&request=GetFeature&typeNames=hurricane:hurricane_point&PROPERTYNAME=(point,strength)&CQL_FILTER=storm_id=%27'+storm_id+'%27%20and%20is_prediction=false&outputFormat=JSON'

      let WeatherIcon = L.Icon.extend({
          options: {
            iconSize:     [17, 17], // size of the icon
            iconAnchor:   [8, 8],   // point of the icon which will correspond to marker's location
            popupAnchor:  [-3, -76] // point from which the popup should open relative to the iconAnchor

      let hurricaneIcon = new WeatherIcon({iconUrl: 'img/hurricane.png'});
      let stormIcon = new WeatherIcon({iconUrl: 'img/storm.png'});
      let depressionIcon = new WeatherIcon({iconUrl: 'img/depression.png'});
      let prestormIcon = new WeatherIcon({iconUrl: 'img/prestorm.png'});
      let poststormIcon = new WeatherIcon({iconUrl: 'img/poststorm.png'});

      .then(function(response) {
        let gjTrack = response.data;

        let track = L.geoJSON(gjTrack, {
          pointToLayer: function(feature, LatLng) {
            var icon;
            switch (feature.properties.strength) {
              case 's': icon = stormIcon; break;
              case 'x': icon = prestormIcon; break;
              case 'm': icon = hurricaneIcon; break;
              case 'h': icon = hurricaneIcon; break;
              case 'd': icon = depressionIcon; break;
              case 'i': icon = poststormIcon; break;
            return L.marker(LatLng, icon);
        L.marker([29.8, -95.4], {icon: stormIcon}).addTo($scope.G.map);
        L.marker([29.9, -95.4], {icon: prestormIcon}).addTo($scope.G.map);
        L.marker([29.9, -95.3], {icon: poststormIcon}).addTo($scope.G.map);
        L.marker([30.0, -95.3], {icon: hurricaneIcon}).addTo($scope.G.map);
        L.marker([30.0, -95.2], {icon: depressionIcon}).addTo($scope.G.map);

I am running this in combination with AngularJS hence the $scope references. At the end I've added some debugging to verify that each of my icons are correctly formed. The L.marker's are showing each icon properly.

  • can you put a break-point inside the pointToLayer function and verify that it's definitely running, and is correctly setting the appropriate icon? Do the LatLng values look correct (maybe the icons are being set, but the points are off-screen)? Oct 3, 2017 at 2:52
  • Hi Stephen, thanks for your response. Yes, the pointToLayer function is definitely running and I observe the LatLng containing appropriate values (I put a breakpoint on the line return L.marker(LatLng, icon); ) and see both variables, one has the point and the other has the icon. I spent some time making a fiddle: jsfiddle.net/n733p7bs/8
    – Strat-O
    Oct 3, 2017 at 4:57
  • I simplified your fiddle even further in an attempt to figure out what's going wrong, and this seems to demonstrate that the pointToLayer function is the problem(?). The storm icon is fine, but pointToLayer isn't setting it. Unfortunately I have no idea why this might be happening. It doesn't seem to be due to variable scope, since it also fails if you put the weatherIcon and stormIcon declarations inside the pointToLayer function. jsfiddle.net/slead/n733p7bs/10 Oct 3, 2017 at 5:33
  • That is great Stephen. You can't get much simpler than that. When I get a chance I will begin learning a bit how Leaflet works by stepping through the pointToLayer function in the Chrome debugger (love that "pretty print" feature they added a while back that enables debugging of minified code)
    – Strat-O
    Oct 3, 2017 at 22:16

1 Answer 1


As always, the answer was blindingly obvious in retrospect ;)

It came down to a simple syntax error: the marker declaration in the pointToLayer function return L.marker(LatLng, icon); should be return L.marker(LatLng, {icon: icon});



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.