Skizzo
Skizzo

Reputation: 2983

How to clear leaflet layer after click

I try to select/deselect the layer using a mouse click. Firstly my map is in this way

After clicking on a layer I want to select it and highlight

Now if I click again on the previously selected layer, I want to deselect it and reset the highlight. This is the code that I use to do this:

  onEachFeature: function(feature,layer) {

      layer.setStyle({fillOpacity: 0.0 , color: '#424a44', weight: 2});
      layer.on('click', function(e) {

      let isLayerAlreadySelected =  // Some logic to undestand if layer alreeady selected

      if(isLayerAlreadySelected) 
         layer.setStyle({fillOpacity: 0.0 , color: '#424a44', weight: 2});
      else
          layer.setStyle({fillOpacity: 0.4 , color: '#004691', weight: 3});
      }

  }

But sometimes when I try to deselect previously selected layer, the layer style is not resetting the opacity remains. Some suggestions about this?

Upvotes: 6

Views: 3676

Answers (5)

Tom
Tom

Reputation: 1

you can prefer a swapping of mouse event functions to perform delection of highlighted layer

layer.setStyle({
                    fillColor: getRandomColor(),
                    fillOpacity: 0.50,
                    stroke: false
                });
                layer.on('mouseover', function(e) {
           highlightFeature(e);
  //open popup;
    var popup = L.popup()
   .setLatLng(e.latlng)
   .setContent(feature.properties.Name)
   .openOn(mymap);

   });
      layer.on('mouseout', function(e) {
           defaultFeature(e);
  //open popup;
    var popup = L.popup()
   .setLatLng(e.latlng)
   .setContent(feature.properties.Name)
   .openOn(mymap);
    });

defaultfeature() is defined to perform deselection

function getRandomColor() {
  var letters = '0123456789ABCDEF';
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}


function highlightFeature(e) {
    highlightLayer = e.target;
    if (e.target.feature.geometry.type === 'LineString') {
      highlightLayer.setStyle({
        color: '#ffff00',
      });
    } else {
      highlightLayer.setStyle({
        fillColor: getRandomColor(),
        fillOpacity: .25
      });
    }
}
function defaultFeature(e) {

    if (e.target!=null) {
      highlightLayer.setStyle({
        color: getRandomColor(),
        fillOpacity:.50
      });
    } else {
      highlightLayer.setStyle({
        fillColor: highlightFeature(),
        fillOpacity: .25
      });
    }
}

Upvotes: 0

Rahul Mahadik
Rahul Mahadik

Reputation: 12271

Simply you can use resetStyle() method to reset given vector layer's style to the original GeoJSON style.

var map = L.map('map').setView([37.8, -96], 4);

	L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
		maxZoom: 18,
		attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
	}).addTo(map);




	// get color depending on population density value
	function getColor(d) {
		return d > 1000 ? '#800026' :
				d > 500  ? '#BD0026' :
				d > 200  ? '#E31A1C' :
				d > 100  ? '#FC4E2A' :
				d > 50   ? '#FD8D3C' :
				d > 20   ? '#FEB24C' :
				d > 10   ? '#FED976' :
							'#FFEDA0';
	}

	function style(feature) {
		return {
			weight: 2,
			opacity: 1,
			color: 'white',
			dashArray: '3',
			fillOpacity: 0.7,
			fillColor: getColor(feature.properties.density)
		};
	}

	function highlightFeature(e) {
    geojson.resetStyle();
		var layer = e.target;

		layer.setStyle({
			weight: 5,
			color: '#666',
			dashArray: '',
			fillOpacity: 0.7
		});

		if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
			layer.bringToFront();
		}

	}

	var geojson;

	function resetHighlight(e) {
		geojson.resetStyle(e.target);
	}

	function zoomToFeature(e) {
		map.fitBounds(e.target.getBounds());
	}
    // Set style function that sets fill color property
function style(feature) {
    return {
        fillColor: '#004691', 
        fillOpacity: 0.5,  
        weight: 1,
        opacity: 1,
        color: '#424a44',
        dashArray: '1'
    };
}
	var highlight = {
		'fillColor': 'yellow',
		'weight': 1,
		'opacity': 1
	};

	function onEachFeature(feature, layer) {
		layer.on({
			
			click: highlightFeature
		});
        
	}

	geojson = L.geoJson(statesData, {
		style: style,
		onEachFeature: onEachFeature
	}).addTo(map);
#map {
         width: 600px;
         height: 400px;
         }
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" crossorigin=""/>
    <script src="https://unpkg.com/[email protected]/dist/leaflet.js"crossorigin=""></script>
      
       <div id='map'></div>
      <script type="text/javascript" src="https://leafletjs.com/examples/choropleth/us-states.js"></script>

You can refer this and this for more info.

Hope this will helps you.

Upvotes: 10

ghybs
ghybs

Reputation: 53205

First you could slightly simplify your code by setting your "base" style using the Leaflet GeoJSON factory style option. That way, your highlight function can reset the style conveniently using the Leaflet GeoJSON Layer Group resetStyle() method:

let selected = false;

function onEachFeature(feature, layer) {
  layer.on("click", function() {
    selected = !selected;
    if (selected) {
      layer.setStyle({
        fillOpacity: 0.4,
        color: '#004691',
        weight: 3
      });
    } else {
      geojsonLayerGroup.resetStyle(layer);
    }
  });
}

const map = L.map('map').setView([48.86, 2.35], 11);

const geojsonData = {
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [2.35, 48.88],
        [2.32, 48.84],
        [2.38, 48.84],
        [2.35, 48.88]
      ]
    ]
  },
  "properties": {}
};

const geojsonLayerGroup = L.geoJSON(geojsonData, {
  onEachFeature: onEachFeature,
  style: {
    fillOpacity: 0.0,
    color: '#424a44',
    weight: 2
  }
}).addTo(map);

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
html,
body,
#map {
  height: 100%;
  margin: 0;
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>

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

Now from your comments, it sounds like you might run in the funny troubles of Angular zone. Actions that occur outside Angular Zone may not be painted by the browser.

If you try deselecting your layer and nothing seems to happen, try another action somewhere else in the browser: click somewhere else, resize the window, etc. If the deselection suddenly triggers, then it is most probably the effect of Angular Zone.

Upvotes: 3

harisu
harisu

Reputation: 1416

You could check by color and or the weight this will mean you have to overwrite the current behavior of highlight(Hover ie both the mouseover and mouseout) behavior so that you can differentiate when there is a click. this will mean doing something like

function onEachFeature(feature, layer) {
    layer.on({
        mouseover: highlightFeature,
        mouseout: resetHighlight,
        click: selectLayer
    });
}

then selectLayer will be as

function selectLayer(e) {
      let isLayerAlreadySelected =  ((e.target.options.color === '#004691') &&(e.target.options.weight === 3))

      if(isLayerAlreadySelected) 
         layer.setStyle({fillOpacity: 0.0 , color: '#424a44', weight: 2});
      else
          layer.setStyle({fillOpacity: 0.4 , color: '#004691', weight: 3});
}

This will mean that the highlightFeature will be as follows

//Here you should set the highlight features different from when its clicked particularly take note of your wight and color since its what we use for the logic.
function highlightFeature(e) {
    let layer = e.target;

    layer.setStyle({
        weight: 1,
        color: '#666',
        fillOpacity: 0.1
    });

}

similarly resetHighlight will be like

//basically you will be putting the styles to their default here what ever values you choosed as default
function resetHighlight(e) {
    let layer = e.target;

    layer.setStyle({
        weight: 0,
        color: '#424a44',
        fillOpacity: 0
    });

}

You might find this documentation useful leaflet layer

Upvotes: 0

Falke Design
Falke Design

Reputation: 11338

You can test which color the layer has:

onEachFeature: function(feature,layer) {

      layer.setStyle({fillOpacity: 0.0 , color: '#424a44', weight: 2});
      layer.on('click', function(e) {

          let isLayerAlreadySelected =  e.target.options.color === '#004691';

          if(isLayerAlreadySelected) 
             e.target.setStyle({fillOpacity: 0.0 , color: '#424a44', weight: 2});
          else
             e.target.setStyle({fillOpacity: 0.4 , color: '#004691', weight: 3});

     });
}

Upvotes: -1

Related Questions