[GIS] How to modify features during runtime, in a GeoJSON feature group on Leaflet

featuresgeojsonleaflet

I have added some GeoJSON to my Leaflet powered map as below. (Altered version)

var array_of_layers = L.layerGroup([]);
var styleholder = [];

var belgium_style = {color: "#d3e46f"};
var bosnia_style = {color: "#f3c1d3"};
var (...)

function styling(name, geoname, color){
    this.numid = count;
    styleholder[count] = this;

    this.name = name;
    this.geoname = geoname; //the geojson filename, just in case.
    this.label = name;
    this.color = color;
    this.opacity = 1;
    this.stroke = false;
    this.fillOpacity = 1;
    this.fillColor = color;

    count++;
}

var belgium_style = new styling("Belgium", "belgium", "#52EB8D");
var bosnia_style = new styling("Bosnia", "bosnia", "#EB9752");
(...)

var everything = L.geoJson(myfile, {
    onEachFeature: function(feature){
        array_of_layers.addLayer(feature);
    },
    style: function(feature){
            switch(feature.properties.name){
            case "belgium": return belgium_style; break;
            case "bosnia": return bosnia_style; break;
            case "denmark": return denmark_style; break;
            case "great_britain": return britain_style; break;
            case "greece": return greece_style; break;
            case "italy": return italy_style; break;
            case "serbia": return serbia_style; break;
            case "spain": return spain_style; break;
            }
    }

});

So the next thing I need to do is, for instance, make a country become blue and all the others gray, when I mouse over it. And, make that possible as well by a function, that I can call whenever I want, regardless of mouse position.

Therefore, during runtime, how do I change the color of any country as I wish? In other words, what is the correct syntax for re-defining the style function for a particular feature?

I have tried to iterate over the styleholder array with a for(var x in styleholder) loop until I get to find the style with the name I want to make blue. By looking at the debugging console, I can tell that I get to find the country, but there's no use changing the color value of a country once it's been created on the map. So the color doesn't change.

The code below sums up what I'm talking about:

var change_color_to_blue = function(country){

for(var a in styleholder){
   if (a.geoname === country){
       a.color = "#0000FF";
       a.fillColor = "#0000FF";
   }
}

change_color_to_blue("belgium");

You see, although it runs without an error, the color remains the same.

The same thing for a mousing-over feature, could be possibly something like this:

everything.on('mouseover', function(e){

var moused_over_country = e.layer;
moused_over_country.color = "#0000FF"; //this is not how it's done

MagicallyMakeAllOtherLayersGray();

refreshgeoJson(); //that does not exist.
refreshMap();     //this neither, most probably.

});

Even this works, and the target country gets blue, how do I make the rest gray?
Is there a way to iterate over every feature in geoJson and reset every style function respectively?

Best Answer

I have written down a small code to modify geojson feature style on runtime using leaflet. you can try it on jsFiddle or use the following code test locally.

I hope it will help.

Here is the code:

<!DOCTYPE html>
<html>
<head>
<title>Leaflet Coloring Geojson Features</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://leafletjs.com/dist/leaflet.css" />
<!--[if lte IE 8]><link rel="stylesheet" href="../dist/leaflet.ie.css" /><![endif]-->
<style>
#map {
    width: 800px;
    height: 500px;
}
.info {
    padding: 6px 8px;
    font: 14px/16px Arial, Helvetica, sans-serif;
    background: white;
    background: rgba(255, 255, 255, 0.8);
    box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
    border-radius: 5px;
}
.info h4 {
    margin: 0 0 5px;
    color: #777;
}
.legend {
    text-align: left;
    line-height: 18px;
    color: #555;
}
.legend i {
    width: 18px;
    height: 18px;
    float: left;
    margin-right: 8px;
    opacity: 0.7;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 
<script src="http://leafletjs.com/dist/leaflet.js"></script> 
<script type="text/javascript" src="http://leafletjs.com/examples/us-states.js"></script> 
<script type="text/javascript">
    $(document).ready(function () {
        init_map();
        init_geojson();
        $("#btn").on('click', function () {
            var stateName = $('#statename').val();
            console.log(stateName);
            init_geojson(stateName);
        });
    });
    var map, geojson, sn;

    function init_map() {
        map = L.map('map').setView([37.8, -96], 4);
        L.tileLayer('http://{s}.tile.cloudmade.com/{key}/22677/256/{z}/{x}/{y}.png', {
            attribution: 'Map data &copy; 2011 OpenStreetMap contributors, Imagery &copy; 2012 CloudMade',
            key: 'BC9A493B41014CAABB98F0471D759707'
        }).addTo(map);
        geojson = L.geoJson(statesData, {
            style: style
            //onEachFeature: onEachFeature,
        }).addTo(map);
    }

    function init_geojson(n) {
        console.log(geojson.options);
        map.removeLayer(geojson);
        if (n != "") {
            sn = n;
            console.log(sn);
            geojson = L.geoJson(statesData, {
                style: style
            }).addTo(map);
        }
    }

    function style(feature) {
        console.log(sn);
        if (sn == feature.properties.name) {
            return {
                weight: 2,
                opacity: 1,
                color: 'white',
                dashArray: '3',
                fillOpacity: 0.3,
                fillColor: '#ff0000'
            };
        } else {
            return {
                weight: 2,
                opacity: 1,
                color: 'white',
                dashArray: '3',
                fillOpacity: 0.3,
                fillColor: '#666666'
            };
        }
    }
</script>
<input type="text" id="statename" value="Alaska">
<input type="button" id="btn" value="Set Color"/>
</body>
</html>