Leaflet Image Overlay Marker dislocating responsive design - leaflet

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);
}

Related

Add polyline to array of markers in 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>

Leaflet JS - Create Map based on static png and draw markers

I was able to generate map using tiles and draw marker
mymap = L.map('map').setView([0, 0], 2);
var panBounds = L.latLngBounds(L.latLng(-300, 300), L.latLng(300, -300));
var mapBounds = L.latLngBounds(L.latLng(180, 180), L.latLng(-180, -180));
var tileLayer = L.tileLayer(tileDirectory + "/{z}/{x}/{y}.png", {
attribution: "test",
maxZoom: 4,
minZoom: 2,
continuousWorld: false,
noWrap: true,
maxBoundsViscosity: 0.0,
bounds: mapBounds //render bound
}).addTo(mymap);
//set panning bounds
mymap.setMaxBounds(panBounds);
But I am looking for way to draw markers on top of static image instead of tile layers. Is this possible with Leaflet JS
Image overlay marker based on pixel co oordinates
var w = 1366,
h = 768
let mymap = new L.Map('map', {
crs : L.CRS.Simple,
attributionControl: false,
maxZoom: 4,
minZoom: 2,
zoom:2
});
var southWest = mymap.unproject(L.point(0, h), mymap.getMaxZoom());
var northEast = mymap.unproject(L.point(w, 0), mymap.getMaxZoom());
var bounds = new L.LatLngBounds(southWest, northEast);
L.imageOverlay(url, bounds).addTo(mymap);
mymap.fitBounds(bounds);
var m = {
x: 692,
y: 287
}
var marker = L.marker(mymap.unproject(L.point(m.x, m.y),
mymap.getMaxZoom())).addTo(mymap);

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);
}