Marie-Louise Journocode Marie-Louise Journocode - 4 years ago 124
Javascript Question

Make Leafletmarkers searchable and blurr out the others

With help of the StackOverflow community I built a leaflet map with markers for blogdata and articledata. The blogdata represents the IDs and geoloations of newsrooms and the articledata are the locations from articles the newsrooms wrote. So there are several articles per newsroom and I connected those with polylines (see picture below).

What I'd like now to do is make that leaflet map searchable, not for cities or countries but for the newsrooms ID. And I'd like to manage blurring all the other markers and lines out and zooming to the searched blog and it's connected articles.

This is what I got so far:

function myFunction() {

var map = L.map('map').setView([51.101516, 10.313446], 6);
// improve experience on mobile
if (map.tap) map.tap.disable();
L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}', {
attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ',
maxZoom: 16
}).addTo(map);
map._layersMinZoom=5;

var newsroomsById = {};

for(i=0; i<newsrooms.length; i++) {
newsroomsById[newsrooms[i].ID] = newsrooms[i];
}

for(i=0; i<articles.length; i++) {
// retrieve newsroom
var newsroom = newsroomsById[articles[i].ID];
// draw your polyline
var latlngs = [
[articles[i].lat, articles[i].long],
[newsroom.lat, newsroom.long]
];

var polyline = L.polyline(latlngs, {
color: 'grey',
weight: 2,
opacity: 0.5,
smoothFactor: 1,
}).addTo(map);

var room_marker = L.circleMarker([newsroom.lat, newsroom.long], {
radius: 3,
color: '#29D3A0',
fillColor: '#29D3A0',
fillOpacity: 1,
}).addTo(map);

room_marker.bindPopup("<strong style='color: #84b819'>Newsroom </strong>" + newsroom.ID + "<br>").openPopup();
var popup = L.popup();

var art_marker = L.circleMarker([articles[i].lat, articles[i].long], {
radius: 2,
color: '#000',
fillColor: '#000',
fillOpacity: 1,
}).addTo(map);
}
}


And this is how the map looks like (black is article, green is newsroom/blog)
enter image description here

EDIT:
To make the map searchable use the Leaflet plugin L.Search.Control

Answer Source

It's difficult to answer the search part of the question. I think you'll have to describe a use case for that.

However, once you have the ID of the newsroom you want to highlight, you can change the opacity of your polylines and circleMarkers using setOption

However, your code needs some adjustments: you need to keep an array of your markers and keep the ID of the newsrooms in the markers.

Another thing: you should not create newsroom markers in the article loop; it creates as many newsroom markers as your number of articles.

Here is a proposition (selection is made by clicking on the newsroom marker):

var selectedNewsroom = 0;

var newsroomsById = {};


// create newsroom markers
var newsroomMarkers = [];

for(i=0; i<newsrooms.length; i++) {
    newsroomsById[newsrooms[i].ID] = newsrooms[i];

    var room_marker = L.circleMarker([newsrooms[i].lat, newsrooms[i].long], {
        radius: 20,
        color: '#000',
        opacity: .4,
        fillOpacity: .4,
      }).addTo(map);

   //room_marker.bindPopup("<strong style='color: #84b819'>Newsroom </strong>" + newsrooms[i].ID + "<br>");

    room_marker.ID = newsrooms[i].ID;  // associate marker with newsroom

    room_marker.on('click', function(e) {
        console.log('clicked on ' + e.target.ID);
        changeSelection(e.target.ID);
    });

    newsroomMarkers.push(room_marker);  // keep marker reference for later
}


// create article markers and connections to newsrooms
var articleMarkers = [];

for(i=0; i<articles.length; i++) {
    // retrieve newsroom
    var newsroom = newsroomsById[articles[i].ID];
    // draw your polyline
    var latlngs = [
      [articles[i].lat, articles[i].long],
      [newsroom.lat, newsroom.long]
    ];

    var polyline = L.polyline(latlngs, {
      color: '#000',
      weight: 1,
      opacity: .4,
      smoothFactor: 1,
    }).addTo(map);

    var art_marker = L.circleMarker([articles[i].lat, articles[i].long], {
          radius: 2,
          color: '#000',
          fillColor: '#000',
          opacity: .4,
          fillOpacity: .4,
        }).addTo(map);

    art_marker.connection = polyline; // associate polyline with marker
    art_marker.newsroomID = newsroom.ID; 

    articleMarkers.push(art_marker); // keep marker reference for later
}


// highlight or blur newsrooms base on which is selected
function changeSelection(newsroomID) {
    // deselect everything
    for(i=0; i<articleMarkers.length; i++) {
        articleMarkers[i].setStyle({ opacity: .4, fillOpacity: .4 });
        articleMarkers[i].connection.setStyle({ opacity: .4 }); 
    }
    for(i=0; i<newsroomMarkers.length; i++) {
        newsroomMarkers[i].setStyle({ opacity: .4, fillOpacity: .4 });  
    }

    if(selectedNewsroom == 0 || selectedNewsroom != newsroomID) {
        selectedNewsroom = newsroomID;

        for(i=0; i<articleMarkers.length; i++) {
            if(articleMarkers[i].newsroomID == newsroomID) {
                articleMarkers[i].setStyle({ opacity: 1, fillOpacity: 1 });
                articleMarkers[i].connection.setStyle({ opacity: 1 });
            }
        }
        for(i=0; i<newsroomMarkers.length; i++) {
            if(newsroomMarkers[i].ID == newsroomID) {
                newsroomMarkers[i].setStyle({ opacity: 1, fillOpacity: 1 });                    
            }
        }           
    }
    else {
        selectedNewsroom = 0;
    }
}

And a working example.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download