Reputation: 2983
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
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
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: '© <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
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: '© <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
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
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