How to highlight features with same property in Leaflet - leaflet

I have a map with many polygons stored in a GeoJSON file. I want to display these polygons on the map whereby polygons with the same feature 'BROAD_CATEGORY' are highlighted on mouseover on the map legend.
The only examples and documentation I have seen to do this relate to number values rather than text strings (e.g. this one).
This is my legend code for the map at the moment:
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend');
labels = ['<strong>Language(s) of Origin</strong>'],
categories = ['Aboriginal clan','Action','Body part','Colour','Function of place','Historic event or place','Industry','Local estate','Nature','Other local places','Person','Place outside Australia','Portmanteau','Ship','Unknown'];
for (var i = 0; i < categories.length; i++) {
div.innerHTML +=
labels.push(
'<i class="circle" style="background:' + getColor(categories[i]) + '"></i> ' +
(categories[i] ? categories[i] : '+'));
}
div.innerHTML = labels.join('<br>');
return div;
};
legend.addTo(map);

Related

marker with polyline while dragging the marker using leaflet

Hi I have connection between marker with polyline like this Image .
I am attaching a sample here.
How Can I make drag possible that when I drag the the marker with polyline.
example , If I drag the marker 3 it should also update the polyline point and where ever I put the marker 3 polyline should connect with marker 3.
I need this type of drag event that can update the polyline also when dragging the marker.
I am using leaflet for this purpose but still unable to solve the dragging logic of marker with polyline.
Here is the sample code I am using
$http.get("db/getConnectionData.php").then(function (response) {
$scope.links1 = response.data.records;
// $scope.showArrow();
angular.forEach($scope.links1, function(value, i) {
var source_panoId = $scope.links1[i].s_panoId;
var dest_panoId = $scope.links1[i].d_panoId;
var sPanoID = $scope.links1[i].sourcePano_id;
var dPpanoID = $scope.links1[i].destPano_id;
angular.forEach($scope.panoramas, function(value, index) {
if($scope.panoramas[index].panoId == source_panoId){
if($scope.links.indexOf($scope.panoramas[index])== -1){
$scope.links.push($scope.panoramas[index]);
}
var SlatLang = $scope.panoramas[index].project_latLng ;
var SLatLngArr = SlatLang.split(",");
var Slat = parseFloat(SLatLngArr[0]);
var Slang = parseFloat(SLatLngArr[1]);
var polypoint1 = [Slat, Slang];
angular.forEach($scope.panoramas, function(value, index1) {
if($scope.panoramas[index1].panoId == dest_panoId){
if($scope.links.indexOf($scope.panoramas[index1])== -1){
$scope.links.push($scope.panoramas[index1]);
}
var DlatLang = $scope.panoramas[index1].project_latLng ;
var DLatLngArr = DlatLang.split(",");
var Dlat = parseFloat(DLatLngArr[0]);
var Dlang = parseFloat(DLatLngArr[1]);
var polypoint2 = [Dlat, Dlang];
// Draw seperate polyline for each connection
polyline = L.polyline([[Slat, Slang],[Dlat, Dlang]],
{
color: 'blue',
weight: 5,
opacity: .7,
}
).addTo(map);
$scope.polycoords.push(polyline);
}
});
}
});
Here is the code that I am using to make drag of marker with polyline
angular.forEach($scope.panoramas, function(value, index4){
$scope.markers[index4].on('dragstart', function(e){
var latlngs = polyline.getLatLngs(),
latlng = $scope.markers[index4].getLatLng();
for (var i = 0; i < latlngs.length; i++) {
if (latlng.equals(latlngs[i])) {
this.polylineLatlng = i;
}
}
});//dragstart
$scope.markers[index4].on('drag', function(e){
var latlngs = polyline.getLatLngs(),
latlng = $scope.markers[index4].getLatLng();
latlngs.splice(this.polylineLatlng, 1, latlng);
polyline.setLatLngs(latlngs);
});//drag
$scope.markers[index4].on('dragend', function(e){
delete this.polylineLatlng;
});//dragEnd
});
First, when creating the marker, remember to pass the draggable option as true, like this:
var marker = L.marker(latLng, { draggable: true });
Now, check which drag event you want to attach a listener to and then call the redraw function of the polyline inside the callback, like this:
// var polyline defined somewhere
marker.on('drag', function (e) {
polyline.redraw();
});
If this doesn't work, please provide sample code so we can work around with it.
Edit
You also need to change the coordinates of the polyline, otherwise redraw will do nothing. Check out this answer on SO and see if it fits your needs.
Edit 2
You're using an array of polylines while the answer just uses one polyline which has the array of coordinates, so in your case you need to use two loops to accomplish the same task. You can make this faster and maybe use an object as a lookup table to get the right polyline for each marker, for example, like this:
var table = {};
// ...
table[marker] = polyline;
Then later you can get the polyline used for each marker. But anyway, here's what I think would work in your case the way it is in the sample (it was a little hard to understand but I hope it works for you).
I don't know where you are putting the second part of your sample (the event handlers) but I assume it's not inside the double loop that is creating the polylines, right? So this is what I came up with:
marker.on('dragstart', function (e) {
var markerLatLng = marker.getLatLng();
this.polylineLatLngs = [];
for (var i = 0; i < $scope.polycoords.length; i++) {
var polyline = $scope.polycoords[i];
var latLngs = polyline.getLatLngs()
for (var j = 0; j < latLngs.length; j++) {
if (markerLatLng.equals(latLngs[j])) {
this.polylineLatLngs.push([i, j]);
}
}
}
});
marker.on('drag', function (e) {
for (var i = 0; i < this.polylineLatLngs.length; i++) {
var polyline = $scope.polycoords[this.polylineLatLngs[i][0]];
var latLngs = polyline.getLatLngs();
var markerLatLng = marker.getLatLng();
latLngs.splice(this.polylineLatLngs[i][1], 1, markerLatLng);
polyline.setLatLngs(latLngs);
}
});
I am getting this type of behavior. Please let me know how I can solve this .
Thank you for your time.
This is the polyline created by getting data from db or by making the connection between panorama.
This Image when I start dragging the marker 2 I got the result like this
This image when I dragged the marker 3.
This type of result I am getting using the source code you provided above.

Leaflet: Pan, center, zoom map to marker location

I'm new to Leaflet and having fun with it so far. I have an interactive map with 170 or so markers around the world. Each marker has a title in the popup. I'd also like to add a "zoom to" link inside of the popup. When the user clicks zoom to, I would like the map to center on the marker and zoom in to a certain zoom level (see image)
The markers are being generated in PHP as a marker array with the title, and lat/longs, and injected into a javascript var called "items."
for (var i = 0; i < items.length; i++) {
marker = new L.marker([items[i][1],items[i][2]])
.bindPopup(items[i][0])
.addTo(map);
}
Keep your markers in an associative array (index must be unique).
Put put a link in your popup text to call a function passing this index as argument.
In your javascript function use panTo or flyTo
Here is some pseudo code:
var markersById = {};
for (var i = 0; i < items.length; i++) {
marker = new L.marker([items[i][1],items[i][2]])
.bindPopup('Center on map')
.addTo(map);
markersById[i] = marker;
}
function centerMapOnPost(markerId) {
map.panTo(markersById[markerId].getLatLng());
}

Leaflet Marker Cluster add weight to marker

I have a leaflet map and I am using the Leaflet.markerCluster plugin to cluster my markers. I have some markers that represent multiple points on the same location. Unfortunately when it gets clustered it only represents one single point. Is there a way to add a weight to each marker? So that the cluster sees it as more than one point?
Basically I am hoping for a clusterWeight property like the follwing:
var newMarker = L.marker(coordinates, {
icon: myIcon,
clusterWeight: 5
});
This propety does not exist however. Anyoneknow of a work around? Thanks!
First you will need to create a marker that supports custom properties. You can do this by extending the default L.Marker like so:
var weightMarker = L.Marker.extend({
options: {
customWeight: 0
}
});
Then you can make use of Leaflet.markercluster's iconCreateFunction to create a custom cluster marker, by changing what is displayed on the marker:
var markers = L.markerClusterGroup({
iconCreateFunction: function(cluster) {
// iterate all markers and count
var markers = cluster.getAllChildMarkers();
var weight = 0;
for (var i = 0; i < markers.length; i++) {
if(markers[i].options.hasOwnProperty("customWeight")){
weight += markers[i].options.customWeight;
}
}
var c = ' marker-cluster-';
if (weight < 10) {
c += 'small';
} else if (weight < 100) {
c += 'medium';
} else {
c += 'large';
}
// create the icon with the "weight" count, instead of marker count
return L.divIcon({
html: '<div><span>' + weight + '</span></div>',
className: 'marker-cluster' + c, iconSize: new L.Point(40, 40)
});
}
});
Demo: https://jsfiddle.net/chk1/0hq1t13t/

Filtering mapbox markcluster

I am trying to filter mapbox markers with custom icons in a markerclustergroup. I can't seem to get the filters working on the markerclustergroup. Here is the relevant part of the code:
var filters = document.getElementById(‘filters’);
var checkboxes = document.getElementsByClassName(‘filter’);
var markers = L.mapbox.featureLayer()
.setGeoJSON(geojson);
var markercluster = new L.MarkerClusterGroup();
markers.on(‘layeradd’, function(e) {
// Create custom markers
var marker = e.layer,
feature = marker.feature;
marker.setIcon(L.icon(feature.properties.icon));
function change() {
// Find all checkboxes that are checked and build a list of their values
var on = [];
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) on.push(checkboxes[i].value);
}
// The filter function takes a GeoJSON feature object
// and returns true to show it or false to hide it.
markers.setFilter(function (f) {
// check each marker’s symbol to see if its value is in the list
// of symbols that should be on, stored in the ‘on’ array
return on.indexOf(f.properties[‘marker-symbol’]) !== -1;
});
return false;
}
// When the form is touched, re-filter markers
filters.onchange = change;
// Initially filter the markers
change();
markercluster.addLayer(markers);
map.addLayer(markercluster);
Here's a working example of filtering marker cluster groups

OpenLayers - Add according popup text to marker array

I have a probably rather basic problem in OpenLayers, it would be really great if someone could help me out on this one.
I have an array of markers, which should each have a different popup box text. However, I fail in applying the according text to a marker. I tried to do this via another array for the content of the popup boxes. However, i couldn't relate the correct text to a marker. Here is my code:
var vs_locations = [
[13.045240, 47.8013271],
[13.145240, 47.8013271],
[13.245240, 47.8013271],
];
var popupContentHTML = [
"Text for marker with loc[0]",
"Text for marker with loc[1]",
"Text for marker with loc[2]"
];
function addVS(){
for (var i = 0; i < vs_locations.length;i++){
var loc = vs_locations[i];
var feature = new OpenLayers.Feature(volksschulen, new OpenLayers.LonLat(loc[0],loc[1],loc[2]).transform(proj4326,proj900913));
feature.closeBox = true;
feature.data.icon = new OpenLayers.Icon('coffeehouse.png');
feature.popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
'autoSize': true,
});
marker = feature.createMarker();
volksschulen.addMarker(marker);
feature.data.popupContentHTML = ; //Here should be the text according to the marker
feature.data.overflow = "auto";
marker.events.register("mousedown", feature, markerClick);
feature.popup = feature.createPopup(feature.closeBox);
map.addPopup(feature.popup);
feature.popup.hide();
}
}
did you try:
feature.data.popupContentHTML = popupContentHTML[i];
assuming the length of your location array matches your text array, both in length anf position