24

I have two overlays http://02d0c8c.netsolhost.com/dev/lcb_census_layers3.html that can be turned on and off with a Layer Control. I’d like the legend for each layer to turn on/off along with the layers.

I am new to JavaScript and new to Leaflet.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Lake Champlain Basin Census Data</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.4.5/leaflet.css" />
<!--[if lte IE 8]>
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.4.5/leaflet.ie.css" />
<![endif]-->

<style>
        #map {
            width: 750px;
            height: 580px;
        }
        .info {
            padding: 6px 8px;
            font: 14px/16px Verdana, Geneva, 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 {
            font-family: Verdana, Geneva, sans-serif;
            margin: 0 0 5px;
            color: #065581;
        }
        .legend {
            line-height: 18px;
            color: #555;
        }
        .legend i {
            width: 18px;
            height: 18px;
            float: left;
            margin-right: 8px;
            opacity: 0.7;
        }
</style>
<script src="http://cdn.leafletjs.com/leaflet-0.4.5/leaflet.js"></script>
</head>

<body>
<div id="map">
<script type="text/javascript" src="js/LCB_Census_Towns.js"></script>

<script type="text/javascript">

        var map = L.map('map').setView([44.3, -73.1], 8);
        var cloudmade = L.tileLayer('http://{s}.tile.cloudmade.com/d2a498d874144e7dae5e7ab4807f3032/{styleId}/256/{z}/{x}/{y}.png', {
            attribution: 'Map data &copy; 2011 OpenStreetMap contributors, Imagery &copy; 2011 CloudMade',
            key: 'BC9A493B41014CAABB98F0471D759707',
            styleId: 22677
        }).addTo(map);

        // control that shows state info on hover
        var info = L.control({position: 'bottomleft'});

        info.onAdd = function (map) {
            this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
            this.update();
            return this._div;
        };

        // method that we will use to update the control based on feature           properties passed
        info.update = function (props) {
            this._div.innerHTML = '<h4>Population Change</h4>' +  (props ?
        '<b>Town: ' + props.NAME10 + '</b><br />Percent change, 1970-2010<br />(2001-2011 in Qu&eacute;bec): <em><strong> ' + props.CHNG_70_10 + '</strong></em>%<br /><br />1970 Population: ' + props.POP1970 + '<br />1980 Population: ' + props.POP1980 + '<br />1990 Population: ' + props.POP1990 + '<br />2000 Population: ' + props.POP2000 + '<br />2010 Population: ' + props.POP2010 
        : '<b>Hover over a town</b>');
        };

        info.addTo(map);

        //STYLES FOR POPULATION CHANGE MAP

        // get color depending on population density value
        function getColor(d) {
            return d > 100  ? '#BD0026' :
                   d > 50  ? '#F03B20' :
                   d > 20  ? '#FD8D3C' :
                   d > 10   ? '#FEB24C' :
                   d > 0   ? '#FED976' :
                   d > -30   ? '#1C9099' :
                              '#1C9099';
        }

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

        //STYLES FOR POPULATION MAP

        // get color for Population Map depending on population value
        function getColor2(d) {
            return d > 20000  ? '#006D2C' :
                   d > 10000  ? '#31A354' :
                   d > 5000  ? '#74C476' :
                   d > 2500   ? '#A1D99B' :
                   d > 0   ? '#C7E9C0' :
                              '#1C9099';
        }

        function style2(feature) {
            return {
                weight: 2,
                opacity: 1,
                color: '#666',
                dashArray: '3',
                fillOpacity: 0.7,
                fillColor: getColor2(feature.properties.POP2010)
            };
        }

        //LAYER FUNCTIONALITY

        var popChange = new L.geoJson(lcbCensusData, {
            style: style,
            onEachFeature: function (feature, layer) {
            var defaultStyle = layer.style,
                that = this;//NEW

            layer.on('mouseover', function (e) {
                this.setStyle({
                weight: 5,
                color: '#666',
                dashArray: '',
                fillOpacity: 0.7
                });

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

                info.update(layer.feature.properties);
            });
            layer.on('mouseout', function (e) {
                popChange.resetStyle(e.target); //NEW
                info.update();
            });
            }
            });

        var population = L.geoJson(lcbCensusData, {
            style: style2,
            onEachFeature: function (feature, layer) {
            var defaultStyle = layer.style,
                that = this;//NEW

            layer.on('mouseover', function (e) {
                this.setStyle({
                weight: 5,
                color: '#666',
                dashArray: '',
                fillOpacity: 0.7
                });

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

                info.update(layer.feature.properties);
            });
            layer.on('mouseout', function (e) {
                population.resetStyle(e.target); //NEW
                info.update();
            });
            }
            }).addTo(map);

        //LAYER CONTROL 
        var overlays = {
            "Population Change,'70-'10": popChange,
            "Population": population
        };

        L.control.layers(null, overlays, {collapsed: false}).addTo(map);

        // LEGEND
        var legend = L.control({position: 'bottomright'});

        legend.onAdd = function (map) {
        var div = L.DomUtil.create('div', 'info legend');

            div.innerHTML +=
            '<img src="legend.png" alt="legend" width="134" height="147">';

        return div;
        };

        legend.addTo(map);

    </script>
</div>
</body>
</html>
PolyGeo
  • 65,136
  • 29
  • 109
  • 338
ryan
  • 241
  • 1
  • 2
  • 3
  • Do you have the second legend available? http://02d0c8c.netsolhost.com/dev/legend.png is the current one. – Mapperz Aug 16 '13 at 19:19
  • I wrote an answer to a more recent question which could also be helpful for soving the problem of this question as it shows two working jsfiddles: https://gis.stackexchange.com/questions/164755/problem-with-legends-leaflet/164808#164808 – Thomas B Oct 08 '15 at 07:21

2 Answers2

24

You could listen for the "overlayadd" and/or the "overlayremove" events on the map object and have two separate legends (two controls) defined, e.g.:

map.on('overlayadd', function (eventLayer) {
    // Switch to the Population legend...
    if (eventLayer.name === 'Population') {
        this.removeControl(populationChangeLegend);
        populationLegend.addTo(this);
    } else { // Or switch to the Population Change legend...
        this.removeControl(populationLegend);
        populationChangeLegend.addTo(this);
    }
});

EDIT: A more complete example:

var populationLegend = L.control({position: 'bottomright'});
var populationChangeLegend = L.control({position: 'bottomright'});

populationLegend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend');
    div.innerHTML +=
    '<img src="legend.png" alt="legend" width="134" height="147">';
return div;
};

populationChangeLegend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend');
    div.innerHTML +=
    '<img src="change_legend.png" alt="legend" width="134" height="147">';
return div;
};

// Add this one (only) for now, as the Population layer is on by default
populationLegend.addTo(map);

map.on('overlayadd', function (eventLayer) {
    // Switch to the Population legend...
    if (eventLayer.name === 'Population') {
        this.removeControl(populationChangeLegend);
        populationLegend.addTo(this);
    } else { // Or switch to the Population Change legend...
        this.removeControl(populationLegend);
        populationChangeLegend.addTo(this);
    }
});

Note that the this keyword in the event listener is the map object i.e. this is the same as map.

Arthur
  • 2,292
  • 1
  • 17
  • 27
  • Thanks, I'm afraid I'll need some hand-holding. Appreciate your help, if you're so inclined... I've defined a second legend (and changed the name of the image in the first) here http://02d0c8c.netsolhost.com/dev/lcb_census_layers4.html. Do I need to change the way I add overlays to the control before using the overlayadd event? – ryan Aug 19 '13 at 17:28
  • You can add the second legend the same way you added the first. I'll edit my answer to provide a more complete example. – Arthur Aug 19 '13 at 19:11
  • Yep, that's what I tried with no luck. How would the if/else statement in the overlayadd event work if both layers were turned on? Seems like population change legend could not be added as long as the population layer was checked. I also tried using the overlays as base layers with radio button toggling, but still didn't work. – ryan Aug 20 '13 at 12:44
0

This code actually works for me!

    var divLegend = `
        <h4>Legend</h4>
        <div id="marker-geo"><i class="icon" style="background-image: url(./assets/marker.svg);background-repeat: no-repeat;"></i><span>Marker GeoJson (Intersect)</span></div>
        <div id="marker-geo-not-intersect"><i class="icon" style="background-image: url(./assets/marker_green.png);background-repeat: no-repeat;"></i><span>Marker GeoJson (Not Intersect)</span></div>
        <div id="ruas-geo"><i style="background: #3388FF"></i><span>Jalan Nasional dari GeoJson</span></div>
        <div id="ruas-zip"><i style="background: #858585"></i><span>Jalan Nasional dari Zip</span></div>
        <div id="marker-zip"><i class="icon" style="background-image: url(https://unpkg.com/leaflet@1.0.3/dist/images/marker-icon.png);background-repeat: no-repeat;"></i><span>Marker Zip</span></div>
    `
function stripSpaces(str){
    return str.replace(/\s+/g, '');
}

var div = L.DomUtil.create("div", "legend"); div.innerHTML = divLegend;

    L.LegendControl = L.Control.extend({
        onAdd: function (map) {


            return div;
        }
    });


    var strDivMarkerUser = &quot;#&quot;+stripSpaces(&quot;marker-user&quot;);
    var strDivMarkerGeo = &quot;#&quot;+stripSpaces(&quot;marker-geo&quot;);
    var strDivRuasGeo = &quot;#&quot;+stripSpaces(&quot;ruas-geo&quot;);
    var strDivRuasZip = &quot;#&quot;+stripSpaces(&quot;ruas-zip&quot;);
    var strDivMarkerZip = &quot;#&quot;+stripSpaces(&quot;marker-zip&quot;);
    var strDivLegend = &quot;#&quot;+stripSpaces(&quot;legend&quot;);
    var strDivNotIntersectMarker = &quot;#&quot;+stripSpaces(&quot;marker-geo-not-intersect&quot;);

    $(document).ready(function(){
        $(strDivMarkerUser).hide();
        $(strDivMarkerGeo).hide();
        $(strDivRuasGeo).hide();
        $(strDivRuasZip).hide();
        $(strDivMarkerZip).hide();
        $(strDivLegend).hide();
        $(strDivNotIntersectMarker).hide();
    });

Then you can add this code for overlayadd logic

map.on('overlayadd', function (e) {
    $(strDivLegend).show();
    if (e.name == "Marker dari url geojson") {
        $(strDivMarkerGeo).show();
        $(strDivNotIntersectMarker).show();
    }
    if (e.name == "Ruas Jalan dari url geojson") {
        $(strDivRuasGeo).show();
    }
    if (e.name == "Ruas Jalan dari file zip") {
        $(strDivRuasZip).show();
    }
    if (e.name == "Marker dari file zip") {
        $(strDivMarkerZip).show();
    }
})

map.on('overlayremove', function (e) { if (e.name == "Marker dari url geojson") { $(strDivMarkerGeo).hide(); } if (e.name == "Ruas Jalan dari url geojson") { $(strDivRuasGeo).hide(); } if (e.name == "Ruas Jalan dari file zip") { $(strDivRuasZip).hide(); } if (e.name == "Marker dari file zip") { $(strDivMarkerZip).hide(); } })

Kadir Şahbaz
  • 76,800
  • 56
  • 247
  • 389