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);
}
Related
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>
I have 3 maps Osm, Lidar and Aerial . I want to select one as the baselayer and one as an overlay. E.g. osm + aerial, osm + Lidar, Aerial + lidar. The LayerControl nearly does what I want but fires baselayerchanged when an overlay is enabled that is also a baselayer optionn. Any ideas on how to sort this would be welcome.
Use two instances of L.Control.Layers, each having a different set of 3 "baselayers".
The nomenclature of "baselayers" and "overlays" can be confusing. As far as a L.Control.Layers is concerned, baselayers are mutually exclusive and overlays are not. You can have something that looks like a graphical overlay but is defined as a baselayer in a control.
Here is the code I ended up with. The important thing is that when changing base layer with an overlay selected, the overlays have to be unloaded to load the new base at the bottom of the z order.
$(document).ready(function () {
var map = L.map('map').setView([-14.0349289249, -171.438639761], 14);
var osm = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors'
});
var aerial =L.tileLayer('aerial/{z}/{x}/{y}.png', {
maxZoom: 18,
tms: false,
attribution: 'Aerial from Centre for Samoan Studies (CSS)'
});
var lidar =L.tileLayer('lidar/{z}/{x}/{y}.png', {
maxZoom: 18,
tms: false,
attribution: 'LIDAR from Centre for Samoan Studies (CSS)'
});
// our set of layers
var layers = [osm, aerial, lidar];
// initial base layer
osm.addTo(map)
// to enable base/overlay swapping, add extra properties with unlikely to clash names
osm.isSamoaBase = true;
osm.isSamoaOverlay = false;
osm.samoaName = 'Base';
lidar.isSamoaBase = false;
lidar.isSamoaOverlay = false;
lidar.samoaName = 'LIDAR';
aerial.isSamoaBase = false;
aerial.samoaName = 'Aerial';
aerial.isSamoaOverlay = false;
// set true when the existing base layer is to be replaced
var baseChange = false;
// layer selector for both base and overlays,
// sorted to preserve order as layers move between base and overlay sections
var layerControl = L.control.layers(null, null, {sortLayers:true});
layerControl.addTo(map);
loadLayerControl(layerControl);
map.on('layerremove', function(le){
if (le.layer.isSamoaBase) {
le.layer.isSamoaBase = false;
// a new base will be selected next
baseChange = true;
}
if (le.layer.isSamoaOverlay) {
le.layer.isSamoaOverlay = false;
}
loadLayerControl(layerControl);
});
map.on('layeradd', function(le){
if (baseChange) {
baseChange = false;
// tag as new base
le.layer.isSamoaBase = true;
le.layer.isSamoaOverlay = false;
// restore full base layer opacity
le.layer.setOpacity(1);
}
if (!le.layer.isSamoaBase) {
le.layer.isSamoaOverlay = true;
}
loadLayerControl(layerControl);
//set opacity from slider for any selected overlays
var val = $('#basemapslider').slider("option", "value");
map.eachLayer(function(layer){
if (layer.isSamoaOverlay) {
layer.setOpacity(val);
}
});
});
function loadLayerControl(lc) {
//remove twice in case both layer both a base and overlay option
for (var i = 0; i < layers.length; i++) {
lc.removeLayer(layers[i]);
lc.removeLayer(layers[i]);
}
// must add base first to get base at bottom of z order
for (var i = 0; i < layers.length; i++) {
if (!layers[i].isSamoaOverlay) {
lc.addBaseLayer(layers[i], layers[i].samoaName);
}
}
// finally add overlays
for (var i = 0; i < layers.length; i++) {
if (!layers[i].isSamoaBase) {
lc.addOverlay(layers[i], layers[i].samoaName);
}
}
}
})
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 © 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
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.
I am creating an interactive map for a non profit association "Friends of Knox Mountain Park" but I am getting trouble with the Google Earth view.
I've been searching on the web for weeks and none of the solutions I found works for me. Can someone take a look of the code and let me know what I should do to include Google Earth View in the map? Thanks in advance.
The online project: http://www.virtualbc.ca/knoxmountain/
And this is the javascript file (mapa2.js) containing the google map's code:
google.load('earth', '1');
var map;
var googleEarth;
var gmarkers = [];
var iconShadow = new google.maps.MarkerImage('icons/shadow.png',
new google.maps.Size(46, 42),
new google.maps.Point(0,0),
new google.maps.Point(13, 42));
var sites = [
['Apex Trail - Shelter',49.91174271, -119.48507050, 4, '<img src="images/apex_point_high.jpg">','magenta','14'],
['Apex Trail',49.91286999, -119.48413424, 3, '<img src="images/apex_point_low.jpg">','lemon','1'],
['Gordon Trail',49.91971281, -119.47954356, 2, '<img src="images/apex_point_low.jpg">','lemon','1'],
['Paul Tomb Bay',49.92555541, -119.47710250, 1, '<img src="images/tomb_bay.jpg">','lemon','1']
];
var infowindow = null;
var overlay;
// Used to make Google Map quard coords to MapCruncher/BingMaps quard coords
function TileToQuadKey ( x, y, zoom)
{
var quad = "";
for (var i = zoom; i > 0; i--)
{
var mask = 1 << (i - 1);
var cell = 0;
if ((x & mask) != 0)
cell++;
if ((y & mask) != 0)
cell += 2;
quad += cell;
}
return quad;
}
function init() {
var centerMap = new google.maps.LatLng(49.909671, -119.482241);
var myOptions = {
zoom: 10,
center: centerMap,
mapTypeId: google.maps.MapTypeId.SATELLITE
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
// Create the tile layers
// ASTER Tile Layer
myASTEROptions = {
getTileUrl : function (a,b) {
return "http://www.virtualbc.ca/knoxmountain/map/" + TileToQuadKey(a.x,a.y,b) + ".png";
},
isPng: true,
opacity: 1.0,
tileSize: new google.maps.Size(256,256),
name: "ASTER",
minZoom:13,
maxZoom:20
}
ASTERMapType = new google.maps.ImageMapType( myASTEROptions );
map.overlayMapTypes.insertAt(0, ASTERMapType);
// Aerial Tile Layer
myAerialOptions = {
getTileUrl : function (a,b) {
return "http://www.virtualbc.ca/knoxmountain/map/" + TileToQuadKey(a.x,a.y,b) + ".png";
},
isPng: true,
opacity: 1.0,
tileSize: new google.maps.Size(256,256),
name: "Aerial",
minZoom:15,
maxZoom:21
}
AerialMapType = new google.maps.ImageMapType( myAerialOptions );
map.overlayMapTypes.insertAt(1, AerialMapType);
var panorama = new google.maps.StreetViewPanorama(map.getDiv());
panorama.setVisible(false);
panorama.set('enableCloseButton', true);
map.setStreetView(panorama);
panorama.setPosition(centerMap);
setMarkers(map, sites);
setZoom(map, sites);
infowindow = new google.maps.InfoWindow({
content: "Loading..."
});
googleEarth = new GoogleEarth(map);
google.maps.event.addListenerOnce(map, 'tilesloaded', addOverlays);
}
/*
This functions sets the markers (array)
*/
function setMarkers(map, markers) {
for (var i = 0; i < markers.length; i++) {
var site = markers[i];
var siteLatLng = new google.maps.LatLng(site[1], site[2]);
var marker = new google.maps.Marker({
position: siteLatLng,
map: map,
title: site[0],
zIndex: site[3],
html: site[4],
// Markers drop on the map
animation: google.maps.Animation.DROP,
icon: 'http://www.virtualbc.ca/knoxmountain/icons/icon.png',
shadow: iconShadow
});
gmarkers.push(marker);
google.maps.event.addListener(marker, "click", function () {
infowindow.setContent(this.html);
infowindow.open(map, this);
});
}
}
/*
Set the zoom to fit comfortably all the markers in the map
*/
function setZoom(map, markers) {
var boundbox = new google.maps.LatLngBounds();
for ( var i = 0; i < markers.length; i++ )
{
boundbox.extend(new google.maps.LatLng(markers[i][1], markers[i][2]));
}
map.setCenter(boundbox.getCenter());
map.fitBounds(boundbox);
}
// This function picks up the click and opens the corresponding info window
function myclick(i) {
google.maps.event.trigger(gmarkers[i-1], "click");
}
google.maps.event.addDomListener(window, 'load', init);
The first issue I notice with your site is you are linking to http://www.virtualbc.ca/src/googleearth-compiled.js which does not exist.