Add polyline to array of markers in Leaflet - leaflet

I'm very new to Leaflet and coding, and I'm basically just trying out to see if I can build a random map with different features. I've come across an issue, which I need help with.
I can't add a polyline to an array (see my attempt below), and secondly, I can't make the map fitBounds.
// Map settings
var map = L.map('map').setView([11.206051, 122.447886], 8);
mapLink =
'OpenStreetMap';
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© ' + mapLink + ' Contributors',
maxZoom: 18,
}).addTo(map);
// Icons -> https://github.com/pointhi/leaflet-color-markers
var myIcon = L.icon({
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-gold.png'
});
// Icons2
var myIcon2 = L.icon({
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-violet.png'
});
// Locations
var locations = [
["LOCATION_1", 11.8166, 122.0942],
["LOCATION_2", 11.9804, 121.9189],
["LOCATION_3", 10.7202, 122.5621],
["LOCATION_4", 11.3889, 122.6277],
["LOCATION_5", 10.5929, 122.6325]
];
// Locations 2
var locations2 = [
["LOCATION_1", 9.8166, 122.0942],
["LOCATION_2", 9.9804, 121.9189]
];
// Add markers
for (var i = 0; i < locations.length; i++) {
marker = new L.marker([locations[i][1], locations[i][2]], {icon: myIcon})
.bindPopup(locations[i][0])
.addTo(map);
}
// Add markers2
for (var i = 0; i < locations2.length; i++) {
marker = new L.marker([locations2[i][1], locations2[i][2]], {icon: myIcon2})
.bindPopup(locations[i][0])
.addTo(map);
}
// Add polyline (NOT WORKING)
var polyline = L.polyline([locations[i][1], locations[i][2]], {color: 'red'}).addTo(map);
// Zoom the map to the polyline (NOT WORKING)
map.fitBounds(polyline.getBounds());
Here's a Fiddle: https://jsfiddle.net/Enounce/kcwngxe0/17/
Thanks in advance!

polyline is outside of the loop so i will only take the last value of locations2.length which is 2
Better use let inside for loops so you won't end up with local for loop variables being exposed outside the for loop block
Moreover if I understood correctly you want to add a polyline between the markers of each locations array, locations and locations2
So you need to have a data format of array of latlngs like so:
var locations2 = [
[9.8166, 122.0942],
[9.9804, 121.9189]
];
to be able to create polylines
You can get that by mapping over the two arrays and returning an array with only lat and longitude.
var polyline = L.polyline(locations.map(location => [location[1], location[2]]), {
color: 'red'
}).addTo(map);
You can do the same for locations2 array
var polyline2 = L.polyline(locations2.map(location2 => [location2[1], location2[2]]), {
color: 'red'
}).addTo(map);
Finally to fit the bounds using both polylines you can simply place the two polyline instances in a featureGroup and get its bounds using getBounds method.
const featureGroup = L.featureGroup();
featureGroup.addTo(map);
featureGroup.addLayer(polyline);
featureGroup.addLayer(polyline2);
map.fitBounds(featureGroup.getBounds());
// Map settings
var map = L.map('map').setView([11.206051, 122.447886], 8);
mapLink =
'OpenStreetMap';
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© ' + mapLink + ' Contributors',
maxZoom: 18,
}).addTo(map);
// Icons -> https://github.com/pointhi/leaflet-color-markers
var myIcon = L.icon({
iconSize: [25, 41],
iconAnchor: [10, 41],
popupAnchor: [2, -40],
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-gold.png'
});
// Icons2
var myIcon2 = L.icon({
iconSize: [25, 41],
iconAnchor: [10, 41],
popupAnchor: [2, -40],
iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-violet.png'
});
// Locations
var locations = [
["LOCATION_1", 11.8166, 122.0942],
["LOCATION_2", 11.9804, 121.9189],
["LOCATION_3", 10.7202, 122.5621],
["LOCATION_4", 11.3889, 122.6277],
["LOCATION_5", 10.5929, 122.6325]
];
// Locations 2
var locations2 = [
["LOCATION_1", 9.8166, 122.0942],
["LOCATION_2", 9.9804, 121.9189]
];
// Add markers
for (let i = 0; i < locations.length; i++) {
marker = new L.marker([locations[i][1], locations[i][2]], {
icon: myIcon
})
.bindPopup(locations[i][0])
.addTo(map);
}
var polyline = L.polyline(locations.map(location => [location[1], location[2]]), {
color: 'red'
}).addTo(map);
console.log(locations.map(location => [location[1], location[2]]))
// Add markers2
for (let i = 0; i < locations2.length; i++) {
marker = new L.marker([locations2[i][1], locations2[i][2]], {
icon: myIcon2
})
.bindPopup(locations[i][0])
.addTo(map);
}
var polyline2 = L.polyline(locations2.map(location2 => [location2[1], location2[2]]), {
color: 'red'
}).addTo(map);
const featureGroup = L.featureGroup();
featureGroup.addTo(map)
featureGroup.addLayer(polyline)
featureGroup.addLayer(polyline2)
map.fitBounds(featureGroup.getBounds());
#map {
height: 700px;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.0.3/dist/leaflet.js"></script>
<div id='map'></div>

Related

Leaflet map. How to apply layer control to custom markers

I have a leaflet map with custom markers.
Recently I added Layer Control so that I can make use of a legend to filter the markers.
I've managed to add the legend however it appears to recreate all the markers on top of my custom ones and filters those instead.
I know I'm doing something wrong in the code but can't figure out where.
How can I filter my custom markers using the legend/layer control ?
Here is my jsfiddle
var markersA = [];
var markersB = [];
var markersC = [];
//Loop through the initial array and add to two different arrays based on the specified variable
for (var i = 0; i < data.length; i++) {
switch (data[i].Category) {
case 1:
markersA.push(L.marker([data[i].lat, data[i].lng]));
break;
case 2:
markersB.push(L.marker([data[i].lat, data[i].lng]));
break;
case 3:
markersC.push(L.marker([data[i].lat, data[i].lng]));
break;
default:
break;
}
}
//add the groups of markers to layerGroups
var groupA = L.layerGroup(markersA);
var groupB = L.layerGroup(markersB);
var groupC = L.layerGroup(markersC);
const myAPIKey = "***";
var tileLayer = {
'Filter drop off Points:': L.tileLayer('http://{s}.tile.cloudmade.com/{key}/22677/256/{z}/{x}/{y}.png')
};
const layer = 'https://api.maptiler.com/maps/uk-openzoomstack-night/{z}/{x}/{y}.png?key=tbRG4BpdjpPfpJ5rjwZY'
const layer2 = 'https://api.maptiler.com/maps/voyager/{z}/{x}/{y}.png?key=tbRG4BpdjpPfpJ5rjwZY'
var osm = L.tileLayer(layer)
const map = L.map('map', {
center: data[data.length - 12],
zoomControl: true,
zoom: 17,
layers: [osm, groupA, groupB, groupC]
});
// 'translate(0,' + (-outerRadius + 7) + ')')
var overlayMaps = {
"<img src= 'https://api.geoapify.com/v1/icon/?type=awesome&color=green&icon=tick&scaleFactor=2&apiKey=6dc7fb95a3b246cfa0f3bcef5ce9ed9a' height=24>Delivered": groupA,
"<img src= 'https://api.geoapify.com/v1/icon/?type=awesome&color=gold&icon=tick&scaleFactor=2&apiKey=6dc7fb95a3b246cfa0f3bcef5ce9ed9a' height=24>Left": groupB,
"<img src= 'https://api.geoapify.com/v1/icon/?type=awesome&color=red&icon=tick&scaleFactor=2&apiKey=6dc7fb95a3b246cfa0f3bcef5ce9ed9a' height=24>Returned": groupC
};
L.control.layers(tileLayer, overlayMaps, {
collapsed: false,
position: 'topright'
}).addTo(map);
var mygeojson = {
type: "FeatureCollection",
features: [],
};
var waypoints = []
var all_points = []
for (i = 0; i < data.length; i++) {
var lng = data[i].lng;
var lat = data[i].lat;
all_points.push([lng, lat]);
if (data[i].Category != 0) {
mygeojson.features.push({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [data[i].lng, data[i].lat]
},
"properties": {
"Icon": data[i].Icon,
"Status": data[i].Status,
"Customer": data[i].Customer,
"Supplier": data[i].Supplier,
"Item Size": data[i]["Item Size"],
"Address": data[i].Address,
"Customer Order": data[i]["Customer Order"],
"Notes": data[i].Notes,
"Instruction": data[i].Instruction
}
});
waypoints.push({
id: data[i].id,
lat: data[i].lat,
lng: data[i].lng
});
}
}
// console.log(mygeojson);
//console.log(all_points);
var polyline = L.polyline(lngLatArrayToLatLng(all_points)).addTo(map);
function lngLatArrayToLatLng(lngLatArray) {
return lngLatArray.map(lngLatToLatLng);
}
function lngLatToLatLng(lngLat) {
return [lngLat[1], lngLat[0]];
}
function IconStyle(feature, latlng) {
switch (feature.properties["Status"]) {
case "Delivered":
var deliveredIcon = new L.icon({
iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=green&icon=tick&scaleFactor=2&apiKey=${myAPIKey}`,
iconSize: [20, 32], // size of the icon
iconAnchor: [0, 22], // point of the icon which will correspond to marker's location
popupAnchor: [-3, -26] // point from which the popup should open relative to the iconAnchor
});
return L.marker(latlng, {
icon: deliveredIcon
});
case "Left":
var leftIcon = new L.icon({
iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=gold&icon=tick&scaleFactor=2&apiKey=${myAPIKey}`,
iconSize: [20, 32], // size of the icon
iconAnchor: [0, 22], // point of the icon which will correspond to marker's location
popupAnchor: [-3, -26] // point from which the popup should open relative to the iconAnchor
});
return L.marker(latlng, {
icon: leftIcon
});
case "Returned":
var returnedIcon = new L.icon({
iconUrl: `https://api.geoapify.com/v1/icon/?type=awesome&color=red&icon=tick&scaleFactor=2&apiKey=${myAPIKey}`,
iconSize: [20, 32], // size of the icon
iconAnchor: [0, 22], // point of the icon which will correspond to marker's location
popupAnchor: [-3, -26] // point from which the popup should open relative to the iconAnchor
});
return L.marker(latlng, {
icon: returnedIcon
});
}
}

Leaflet Image Overlay Marker dislocating responsive design

When we try to place a marker in responsive design the markers are dislocating.
Try the following code, fiddle link is added in the comments below for reference.
var osmUrl= 'http://skolavefurinn.is/sites/default/files/styles/quiz_hotspot/public/image_520470007.png',
h = 709,
w = 709;
var map = L.map('mapid', {
minZoom: -3,
maxZoom: 1,
center: [0, -709],
zoom: 1,
crs: L.CRS.Simple
});
var southWest = map.unproject([0, h], map.getZoom());
var northEast = map.unproject([w, 0], map.getZoom());
var bounds = new L.LatLngBounds(southWest, northEast);
var imgOv = L.imageOverlay(osmUrl, bounds).addTo(map);
map.setMaxBounds(bounds);
var markerData = [[0,0],[185,362],[277,593],[307,354],[472,472],[473,568],[550,516],[535,370],[230,119]];
for (var i=0; i<markerData.length; i++){
L.marker(
map.layerPointToLatLng(
map.containerPointToLayerPoint(
markerData[i]
)
)
).addTo(map);
}

Automatically Zoom the map to fit all markers

Following an example, you can see the plunker her http://plnkr.co/edit/lJHyP3dhT3v8aHVdt3D3?p=preview
Regardless of whatever zoom value is provided while initializitng the map, I want to zoom the map automatically so all the markers are inside the view. Here is my code
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '© OpenStreetMap contributors, Points &copy 2012 LINZ'
}),
latlng = L.latLng(-37.82, 175.24);
var map = L.map('map', {center: latlng, zoom: 10, layers: [tiles]});
var markers = L.markerClusterGroup();
for (var i = 0; i < addressPoints.length; i++) {
var a = addressPoints[i];
var title = a[2];
var marker = L.marker(new L.LatLng(a[0], a[1]), { title: title });
marker.bindPopup(title);
markers.addLayer(marker);
}
map.addLayer(markers);
var group = new L.featureGroup(markers);
map.fitBounds(group.getBounds());
You need to
create an array
push all your markers in array
once all the markers are added to array, create a featureGroup
add your markers array to featureGroup and then zoom to its bounds.
Below is the modified code
var markerArray = []; //create new markers array
for (var i = 0; i < addressPoints.length; i++) {
var a = addressPoints[i];
var title = a[2];
var marker = L.marker(new L.LatLng(a[0], a[1]), { title: title });
marker.bindPopup(title);
markers.addLayer(marker);
markerArray.push(marker); //add each markers to array
if(i==addressPoints.length-1){//this is the case when all the markers would be added to array
var group = L.featureGroup(markerArray); //add markers array to featureGroup
map.fitBounds(group.getBounds());
}
}
Here is the working plunk

find associated polylines for selected marker/circlemarker/point in leaflet

I have a multiple circlemarkers on map.
I want to find how many polylines passes through that marker & want to remove that polyline & If polyline does not exists then I want to add polyline.
I am using leaflet.
<script type="text/javascript">
function init(){
var map = L.map('map').setView([51.49521, -0.10062], 13);
L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade'
}).addTo(map);
// get all 6 points
var points = [
[51.49346, -0.11518],
[51.49827, -0.06763],
[51.48331, -0.08154],
[51.52284, -0.09974],
[51.51932, -0.06695],
[51.50949, -0.1363]
];
// polyline
var selection = [];
var polyline = new L.Polyline([], {
color: 'blue',
weight: 5,
smoothFactor: 1
}).addTo(map);
var changeMarkerState = function (marker, select) {
if (marker instanceof L.CircleMarker) {
if (select) {
marker.setRadius(25);
} else {
marker.setRadius(10);
}
}
if (marker instanceof L.Marker) {
if (select) {
marker.options.title = 'selected';
} else {
marker.options.title = 'unselected';
}
marker.setIcon(new L.Icon.Default());
}
};
var onClick = function () {
var index = selection.indexOf(this);
if (index !== -1) {
changeMarkerState(this, false);
selection.splice(index, 1);
polyline.spliceLatLngs(index, 1);
} else {
changeMarkerState(this, true);
selection.push(this);
polyline.addLatLng(this.getLatLng())
}
};
// centerpoint
var centerPoint = new L.LatLng(51.49521, -0.10062);
var marker1 = L.marker([51.49521, -0.10062],
{title: 'unselected'}).on('click', onClick).addTo(map);
// adding allo points to map
for (var i = 0, l = points.length; i < l; i++)
{
// here I can use marker also(if solution is possible with markers)
L.circleMarker(points[i]).on('click', onClick).addTo(map);
var myPoint = new L.LatLng(points[i][0],points[i][1]);
var myPointList = [myPoint, centerPoint];
var firstpolyline = new L.Polyline(myPointList, {
color: 'red',
weight: 5,
smoothFactor: 1
}).addTo(map);
}
}
</script>
In above code what I am doing is that I am drawing multiple red polylines from different circlemarkers to one center point.
On selection of two circle markers I am drawing blue polyline between them.
At same time I want to remove the red polyline which there between circlemarkers & centerpoint.
Also If circlemarker is unselected then that red polyline between that circlemarker & centerpoint should be added.
To compare two latlngs use L.LatLng.equals: https://github.com/Leaflet/Leaflet/blob/master/src/geo/LatLng.js#L24.
To get latlngs from polyline use L.Polyline.getLatLngs: https://github.com/Leaflet/Leaflet/blob/master/src/layer/vector/Polyline.js#L34.
Now you can get your point in polyline and remove it using L.Polyline.spliceLatLngs: https://github.com/Leaflet/Leaflet/blob/master/src/layer/vector/Polyline.js#L48 or add using L.Polyline.addLatLng: https://github.com/Leaflet/Leaflet/blob/master/src/layer/vector/Polyline.js#L43 or set using L.Polyline.setLatLngs: https://github.com/Leaflet/Leaflet/blob/master/src/layer/vector/Polyline.js#L38.

select two markers & draw line between them in leaflet

I am very much new to leaflet.
I have multiple markers/circle Markers plotted on my map in leaflet.
now I have to draw line between two markers//circle Markers when I select them.
Can any one help in doing this.
var map = L.map('map').setView([51.49521, -0.10062], 13);
L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade'
}).addTo(map);
// get all 6 points
var points = new Array(
[51.49346, -0.11518],
[51.49827, -0.06763],
[51.48331, -0.08154],
[51.52284, -0.09974],
[51.51932, -0.06695],
[51.50949, -0.1363]
);
// centerpoint
var centerPoint = new L.LatLng(51.49521, -0.10062);
var marker1 = L.marker([51.49521, -0.10062]).addTo(map);
// adding allo points to map
for (var i =0 ; i < points.length; i++)
{
// here I can use marker also(if solution is possible with markers)
L.circleMarker([points[i][0],points[i][1]]).addTo(map);
var point = new L.LatLng(points[i][0],points[i][1]);
var pointList = [point, centerPoint];
var firstpolyline = new L.Polyline(pointList, {
color: 'red',
weight: 5,
smoothFactor: 1
}).addTo(map);
}
You must store selection (however it can be polyline points or flag in your markers). When you select two or more markers you must add points to you polyline - it draws line on map, otherwise you must remove point from polyline. See details about polyline: http://leafletjs.com/reference.html#polyline.
See next code for example:
// Init map
var map = L.map('map').setView([53.902257, 27.561640], 13);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
// Init selection and lines logic
var selection = [];
var polyline = L.polyline([], {color: 'red'}).addTo(map);
var onClick = function () {
var index = selection.indexOf(this);
if (index !== -1) {
this.setRadius(10);
selection.splice(index, 1);
polyline.spliceLatLngs(index, 1);
} else {
this.setRadius(25);
selection.push(this);
polyline.addLatLng(this.getLatLng())
}
};
// Init circle markers
L.circleMarker([53.90, 27.56]).on('click', onClick).addTo(map);
L.circleMarker([53.92, 27.60]).on('click', onClick).addTo(map);
L.circleMarker([53.88, 27.60]).on('click', onClick).addTo(map);
// Init selection droping on ESC pressed
L.DomEvent.on(document, 'keydown', function (e) {
if (e.keyCode === 27) {
var oldSelection = selection.slice(0);
for (var i = 0, l = oldSelection.length; i < l; i++) {
oldSelection[i].fire('click');
}
}
});
UPD:
It's analogically, see updated code:
var map = L.map('map').setView([51.49521, -0.10062], 13);
L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade'
}).addTo(map);
// get all 6 points
var points = [
[51.49346, -0.11518],
[51.49827, -0.06763],
[51.48331, -0.08154],
[51.52284, -0.09974],
[51.51932, -0.06695],
[51.50949, -0.1363]
];
// polyline
var selection = [];
var polyline = new L.Polyline([], {
color: 'red',
weight: 5,
smoothFactor: 1
}).addTo(map);
var changeMarkerState = function (marker, select) {
if (marker instanceof L.CircleMarker) {
if (select) {
marker.setRadius(25);
} else {
marker.setRadius(10);
}
}
if (marker instanceof L.Marker) {
if (select) {
marker.options.title = 'selected';
} else {
marker.options.title = 'unselected';
}
marker.setIcon(new L.Icon.Default());
}
};
var onClick = function () {
var index = selection.indexOf(this);
if (index !== -1) {
changeMarkerState(this, false);
selection.splice(index, 1);
polyline.spliceLatLngs(index, 1);
} else {
changeMarkerState(this, true);
selection.push(this);
polyline.addLatLng(this.getLatLng())
}
};
// centerpoint
var centerPoint = new L.LatLng(51.49521, -0.10062);
var marker1 = L.marker([51.49521, -0.10062],
{title: 'unselected'}).on('click', onClick).addTo(map);
// adding allo points to map
for (var i = 0, l = points.length; i < l; i++)
{
// here I can use marker also(if solution is possible with markers)
L.circleMarker(points[i]).on('click', onClick).addTo(map);
}