Why the marker position was incorrect occasionally? - leaflet

I'm new to Leaflet map, and I use the OpenStreetMap to show the device location, I confuse why occasionally I got the incorrect marker position for the same latitude and longitude? (it's very far away from the real location).
what did I miss?
my javasript codes below looks correct (I have double check it)
renderMap(-6.208763, 106.845599, address, 14);
var marker;
var deviceLocation;
var geoFencing;
function renderMap(lat, lon, address, zoom)
{
if ($('#device-location').length)
{
if (deviceLocation == undefined)
{
deviceLocation = L.map('device-location');
}
else
{
deviceLocation.off();
deviceLocation.remove();
deviceLocation = L.map('device-location');
}
var latLon = new L.LatLng(lat,lon)
console.log(latLon);
deviceLocation.setView(latLon, 14);
deviceLocation.locate({
watch: false,
setView: false,
timeout: 10000,
enableHighAccuracy: false
});
function onLocationFound(e)
{
var radius = e.accuracy;
//console.log(e.latlng + " " + radius);
marker = L.marker(e.latlng)
.addTo(deviceLocation)
.bindPopup((geoFenceFound ?
'<strong>Your device</strong> is somewhere around ' + radius + ' meters from this point.</br></br>'
))
.openPopup();
var circle = L.circle(e.latlng, radius).addTo(deviceLocation);
var LatLonBounds = circle.getBounds();
geoFencing = circle;
if (geoFenceFound)
deviceLocation.fitBounds(LatLonBounds);
}
function onLocationError(e)
{
showWarning(e.message);
}
function onZoomEnd(e)
{
if (marker != undefined)
{
console.log('onZoomEnd: ' + marker.getLatLng());
deviceLocation.panTo(marker.getLatLng());
}
}
function onResize(e)
{
if (marker != undefined)
{
console.log('onResize: ' + marker.getLatLng());
deviceLocation.panTo(marker.getLatLng());
}
}
deviceLocation.on('locationfound', onLocationFound);
deviceLocation.on('locationerror', onLocationError);
deviceLocation.on('zoomend', onZoomEnd);
deviceLocation.on('resize', onResize);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(deviceLocation);
}
}

Related

Leaflet: Moving the map doesn't move the icons with it, instead the icons stay fixed to the same position on the page

Moving the map doesn't move the icons with it, instead the icons stay fixed to the same position on the page.
My icons get added to the correct latitude and longitude on my map. However, when I drag the map, the icons stay fixed on the same position on the page and are no longer being displayed at the correct latitude and longitude.
let sMap;
let ciLayer;
let neutralMarkers = [];
let gVesselIcons = {};
let numOfVessels = 0;
let ROI;
let nwLat;
let nwLon;
let seLat;
let seLon;
window.indexedDB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB;
//prefixes of window.IDB objects
window.IDBTransaction =
window.IDBTransaction ||
window.webkitittIDBTransaction ||
window.msIDBTransaction;
window.IDBKeyRange =
window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
let db;
const [dbPromise, dbResolve, dbReject] = (() => {
let resolve, reject;
return [
new Promise((res, rej) => {
resolve = res;
reject = rej;
}),
resolve,
reject
];
})();
let dbGSTSStore = window.indexedDB.open('GSTSStore', 1);
let dbVessels;
let dbTransactions;
let dbMessages;
dbGSTSStore.onerror = function(event) {
dbReject();
console.log('error: ');
};
dbGSTSStore.onsuccess = function(event) {
dbResolve();
db = dbGSTSStore.result;
};
dbGSTSStore.onupgradeneeded = function(event) {
const db = event.target.result;
dbVessels = db.createObjectStore('vessels', {
keyPath: 'mmsi'
});
dbMessages = db.createObjectStore('messages', {
keyPath: 'id'
});
dbTransactions = db.createObjectStore('transactions', {
keyPath: 'id'
});
};
async function InitializeSimple(
pBuildNumber,
pSysPersonId,
pSysOrganizationId
){
await GetOrganizationPrefs(pSysOrganizationId);
await GetPersonPrefs(pSysPersonId);
SetLabelText('lblBuildNumber', `Build: ${pBuildNumber}`);
dragElement(document.getElementById("vessel-info"));
nwLat = gOrganizationPrefs.roinwse.nwlat || gPersonPrefs.aoi.nwlat;
nwLon = gOrganizationPrefs.roinwse.nwlon || gPersonPrefs.aoi.nwlon;
seLat = gOrganizationPrefs.roinwse.selat || gPersonPrefs.aoi.selat;
seLon = gOrganizationPrefs.roinwse.selon || gPersonPrefs.aoi.selon;
try {
sMap = L.map('map-content', {
fullscreenControl: false,
zoomControl: false,
zoom: 6,
attributionControl: false,
preferCanvas: true
}).setView([19, 55]);
ciLayer = L.canvasIconLayer({}).addTo(sMap);
L.tileLayer(MapUrl[0], {
attribution: MapAttribution[0],
zoom: 5,
minZoom: 4,
maxNativeZoom: 13,
maxZoom: 20
}).addTo(sMap);
}
catch (error) {
console.log("error initializing map\n");
}
// SetVesselUpdate();
if(gOrganizationPrefs) await SetROI(gOrganizationPrefs.roinwse);
else await SetROI(gPersonPrefs.aoi);
await CreateNeutralLayer();
}
function SetLabelText(pLabel, pText) {
const lLabel = document.getElementById(pLabel);
if (lLabel !== undefined) lLabel.textContent = pText;
}
function CreateNeutralLayer(){
return new Promise((resolve, reject) => {
try {
const lTransaction = db.transaction(['vessels'], 'readonly');
let vessels = lTransaction.objectStore('vessels');
const countRequest = vessels.count();
countRequest.onsuccess = function() {
numOfVessels = countRequest.result;
}
vessels.openCursor().onsuccess = function(e) {
let cursor = e.target.result;
if (cursor !== null) {
let value = cursor.value;
let latitude = value.lat;
let longitude = value.lon;
let canInclude = checkROIBoundaries(latitude, longitude);
if (canInclude && cursor.value !== undefined) {
AddToLayers(cursor.value);
}
cursor.continue();
}
}
resolve('OK');
}
catch (err) {
console.log("error is: ", err, "\n");
reject({ error: err, function: 'CreateNeutralLayer()'});
}
});
}
function AddToLayers(vessel) {
let vesselRotationDegree = vessel.headingdegree.toString().padStart(2, '0');
if (vesselRotationDegree == '32') vesselRotationDegree = '00';
let vesselIconType = 'type-3';
let gBaseRiskIconURL = `./public/img/vessel/${vesselIconType}/vessel-`;
let gBaseRiskNeutralUrl = `${gBaseRiskIconURL}neutral-`;
var vIcon = L.icon({
iconUrl: `${gBaseRiskNeutralUrl}${vesselRotationDegree}.svg`,
iconSize: [24, 24],
iconAnchor: [24, 24]
});
const marker = L.marker([vessel.lat, vessel.lon], { icon: vIcon});
marker.properties = {
vesselname: vessel.shipname,
mmsi: vessel.mmsi,
imo: vessel.imo,
lat: vessel.lat,
lon: vessel.lon,
datetime: vessel.received_time,
heading: vessel.hdg,
sog: vessel.sog,
shiptype_descr: vessel.shiptype_descr,
last_positional_update: vessel.last_updated
};
marker.bindPopup(popupNeutralMarker, {
maxWidth: 392,
className: `map-info`
});
neutralMarkers.push(marker);
if (neutralMarkers.length >= numOfVessels) {
ciLayer.addLayers(neutralMarkers);
const vesselsInROI = document.getElementById('vessels-in-roi');
vesselsInROI.innerHTML = numOfVessels;
}
}
function checkROIBoundaries(latitude, longitude) {
let canInclude = false;
const lLatOK =
latitude >= Math.min(nwLat, seLat) &&
latitude <= Math.max(nwLat, seLat);
const lLonOK =
longitude >= Math.min(nwLon, seLon) &&
longitude <= Math.max(nwLon, seLon);
if (lLatOK && lLonOK) canInclude = true;
else numOfVessels--;
return canInclude;
}
function SetROI(pROI) {
return new Promise((resolve, reject) => {
try {
if (pROI.nwlat + pROI.nwlon + pROI.selat + pROI.selon === 0) return;
const defaultBoundaryStyle = {
color: 'blue',
fillColor: 'lightblue',
fillOpacity: 0.2
}
ROI = new L.rectangle(
[
[pROI.selat, pROI.selon],
[pROI.nwlat, pROI.selon],
[pROI.selat, pROI.selon],
[pROI.selat, pROI.nwlon]
],
defaultBoundaryStyle
)
sMap.addLayer(ROI, true);
// Center ROI
sMap.fitBounds([
[gOrganizationPrefs.roinwse.nwlat, gOrganizationPrefs.roinwse.nwlon],
[gOrganizationPrefs.roinwse.selat, gOrganizationPrefs.roinwse.selon]
]);
resolve('OK');
}
catch (err) {
console.log("error is: ", err, "\n");
reject({ error: err, function: 'SetROI'});
}
})
}

One pushpin click opens them all

Need help troubleshooting. All of the pushpins open upon clicking a single one opens up every pushpin infobox. I want there to be one pushpin infobox that changes each time a pushpin is clicked, only allowing one infobox to be open at a time.
// BING MAP Java Script
var map = null;
var pinid = 0;
var arrPinInfobox = [];
//Bing V8 start
function GetMap() { //LocInfo, Lat, Long
var _MapElement = document.getElementById("myMap");
if (_MapElement === null || typeof _MapElement === "undefined")
return;
if(jQuery("#pagesitemap_4_noMap").length < 0)
return;
var arrLocInfoRec = [];
var arrLLAdder = [];
var MapCenterLat;
var MapCenterLong;
var ZoomFactor;
var ZipLLSource = jQuery("#hdnZipLL").val();
var LocInfo = jQuery("#hdnCompleteLocInfo").val();
var ZipLL = [];
var Lat = "";
var Long ="";
console.log("Long");
if(typeof LocInfo === "undefined")
{
console.log("locInfo Undefined");
return;
}
if (ZipLLSource.length > 0) {
ZipLL = (ZipLLSource).split("`");
}
if (LocInfo.length > 0) {
arrLocInfoRec = LocInfo.split("|")
}
if (Lat.length > 0 && Long.length > 0) {
MapCenterLat = parseFloat(Lat);
MapCenterLong = parseFloat(Long);
ZoomFactor = 11; //16
}
else if (ZipLL.length >= 2) {
MapCenterLat = parseFloat(ZipLL[0]);
MapCenterLong = parseFloat(ZipLL[1]);
ZoomFactor = 11;
}
var mapOptions = {
credentials: ' ',
center: new Microsoft.Maps.Location(MapCenterLat, MapCenterLong),
mapTypeId: Microsoft.Maps.MapTypeId.Automatic,
zoom: ZoomFactor,
showScalebar: true
}
map = new Microsoft.Maps.Map('#myMap', mapOptions);
var arrPins = [];
var arrPinCenter = [];
//Generating Pins for multiple locations with Lat,Long
for (var locNum = 0; locNum <= arrLocInfoRec.length - 1; locNum++) {
try {
arrLLAdder = arrLocInfoRec[locNum].split("`");
if (arrLLAdder.length >= 13) {
//var latlong = arrLLAdder[11].split(',');
arrPinCenter[locNum] = new Microsoft.Maps.Location(parseFloat(arrLLAdder[11]), parseFloat(arrLLAdder[12]));
arrPinCenter[locNum] = new Microsoft.Maps.Location(parseFloat(arrLLAdder[11]), parseFloat(arrLLAdder[12]));
arrPins[locNum] = new Microsoft.Maps.Pushpin(
arrPinCenter[locNum], {
text: arrLLAdder[8] ,
icon: 'https://www.bingmapsportal.com/Content/images/poi_custom.png',
anchor: new Microsoft.Maps.Point(12, 39)
}
);
var adder = arrLLAdder[2] + '\r\n' + arrLLAdder[4] + '\r\n' + arrLLAdder[6] + arrLLAdder[9] + "\r\n" + arrLLAdder[1]
// Create the infobox for the pushpin
arrPinInfobox[locNum] = new Microsoft.Maps.Infobox(arrPins[locNum].getLocation(),
{ width: 350,
height: 100,
title: arrLLAdder[5],
description: adder,
offset: new Microsoft.Maps.Point(-3,13),
visible: false
});
// Add handler for the pushpin click event.
Microsoft.Maps.Events.addHandler(arrPins[locNum], 'click', displayInfobox);
// Add the Push Pins and InfoBox to the map all at once
if(arrPins.length > 0) {
map.entities.push(arrPins); //[locNum]
}
}
else {
console.log("Invalid Data: arrLocInfoRec[" + locNum + "] = \"" + arrLocInfoRec[locNum] + "\"");
}
} catch (e) {
console.log(e.message + "\r\n" + arrLocInfoRec[locNum]);
}
}
}
function displayInfobox(e) {
//map.entities.push(arrPinInfobox);
console.log("DisplayBox");
for(var i in arrPinInfobox){
arrPinInfobox[i].setOptions({ visible: true });
arrPinInfobox[parseInt(e.target.getText()) - 1].setOptions({ visible: true });
var infobox = arrPinInfobox[i];
infobox.setMap(map);
}
}
Your code in the displayInfobox function loops through all your infoboxes and sets visible to true and adding them to the map. Your code is functioning how it was written.
What you want to do is filter out your infoboxes. Personally I hate the whole array of infobox idea, it is messy. I believe I've recommended before the idea of creating a single infobox and reusing it when a pushpin is clicked. That is the best approach if you only need one infobox to appear at a time. If you want to be able to show multiple infoboxes at a time, store the reference to the infobox in the pushpin some how. All shapes in Bing Maps has a metadata property reserved for your custom data. Also just noticed you add the array of pushpins to the map several times, this will cause issues. Here is a proposed change to your code, I've added a comment with // Ricky: to indicate the changes I made:
// BING MAP Java Script
var map = null;
var pinid = 0;
var arrPinInfobox = [];
//Bing V8 start
function GetMap() { //LocInfo, Lat, Long
var _MapElement = document.getElementById("myMap");
if (_MapElement === null || typeof _MapElement === "undefined")
return;
if(jQuery("#pagesitemap_4_noMap").length < 0)
return;
var arrLocInfoRec = [];
var arrLLAdder = [];
var MapCenterLat;
var MapCenterLong;
var ZoomFactor;
var ZipLLSource = jQuery("#hdnZipLL").val();
var LocInfo = jQuery("#hdnCompleteLocInfo").val();
var ZipLL = [];
var Lat = "";
var Long ="";
console.log("Long");
if(typeof LocInfo === "undefined")
{
console.log("locInfo Undefined");
return;
}
if (ZipLLSource.length > 0) {
ZipLL = (ZipLLSource).split("`");
}
if (LocInfo.length > 0) {
arrLocInfoRec = LocInfo.split("|")
}
if (Lat.length > 0 && Long.length > 0) {
MapCenterLat = parseFloat(Lat);
MapCenterLong = parseFloat(Long);
ZoomFactor = 11; //16
}
else if (ZipLL.length >= 2) {
MapCenterLat = parseFloat(ZipLL[0]);
MapCenterLong = parseFloat(ZipLL[1]);
ZoomFactor = 11;
}
var mapOptions = {
credentials: ' ',
center: new Microsoft.Maps.Location(MapCenterLat, MapCenterLong),
mapTypeId: Microsoft.Maps.MapTypeId.Automatic,
zoom: ZoomFactor,
showScalebar: true
}
map = new Microsoft.Maps.Map('#myMap', mapOptions);
var arrPins = [];
var arrPinCenter = [];
//Generating Pins for multiple locations with Lat,Long
for (var locNum = 0; locNum <= arrLocInfoRec.length - 1; locNum++) {
try {
arrLLAdder = arrLocInfoRec[locNum].split("`");
if (arrLLAdder.length >= 13) {
//var latlong = arrLLAdder[11].split(',');
arrPinCenter[locNum] = new Microsoft.Maps.Location(parseFloat(arrLLAdder[11]), parseFloat(arrLLAdder[12]));
arrPins[locNum] = new Microsoft.Maps.Pushpin(arrPinCenter[locNum], {
text: arrLLAdder[8] ,
icon: 'https://www.bingmapsportal.com/Content/images/poi_custom.png',
anchor: new Microsoft.Maps.Point(12, 39)
});
var adder = arrLLAdder[2] + '\r\n' + arrLLAdder[4] + '\r\n' + arrLLAdder[6] + arrLLAdder[9] + "\r\n" + arrLLAdder[1]
// Create the infobox for the pushpin
//Ricky: Add your infobox as a reference in your pushpin
arrPins[locNum]. metadata = new Microsoft.Maps.Infobox(arrPins[locNum].getLocation(),
{ width: 350,
height: 100,
title: arrLLAdder[5],
description: adder,
offset: new Microsoft.Maps.Point(-3,13),
visible: false
});
// Add handler for the pushpin click event.
Microsoft.Maps.Events.addHandler(arrPins[locNum], 'click', displayInfobox);
}
else {
console.log("Invalid Data: arrLocInfoRec[" + locNum + "] = \"" + arrLocInfoRec[locNum] + "\"");
}
} catch (e) {
console.log(e.message + "\r\n" + arrLocInfoRec[locNum]);
}
}
// Add the Push Pins and InfoBox to the map all at once
//Ricky: Moved this out of the array as you only need to add array of pushpins to the map once.
if(arrPins.length > 0) {
map.entities.push(arrPins); //[locNum]
}
}
function displayInfobox(e) {
//map.entities.push(arrPinInfobox);
console.log("DisplayBox");
//Get infobox from the pushpin, rather than looping through array.
var infobox = e.target.metadata;
infobox.setOptions({ visible: true });
//for(var i in arrPinInfobox){
//arrPinInfobox[i].setOptions({ visible: true });
//arrPinInfobox[parseInt(e.target.getText()) - 1].setOptions({ visible: true });
//var infobox = arrPinInfobox[i];
//infobox.setMap(map);
//}
}
If you want to clean up your code some more I recommend:
get rid of all the array's, there is no need for them.
Use a layer for your pushpins. Add a single click event on the layer rather than on each individual pushpin.

leaflet : Prevent marker to be dragged outside the map container

Please consider the following code http://jsfiddle.net/franckl/311bcbc8/
var southWest = L.latLng(-90, -180),
northEast = L.latLng(90, 180);
var bounds = L.latLngBounds(southWest, northEast);
var map = L.map('map', {
minZoom: 2,
zoomControl: false,
attributionControl: false,
maxBounds: bounds
});
// Using cartoDB basemap
L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
minZoom: 2,
subdomains: 'abcd',
detectRetina: true,
attribution: ''
}).addTo(map);
map.fitBounds(bounds);
var newMarker0 = L.marker(map.getCenter(), {
icon: new L.Icon.Default(),
zIndexOffset: 10000,
draggable: true
});
newMarker0.addTo(map);
html
<div id="mycontainer">
<div id="map"></div>
</div>
css
body {
margin:0;
padding:0;
}
#map {
position:absolute;
top:0;
bottom:0;
width:300px;
}
#mycontainer {
top: 10px;
width: 600px;
height: 250px;
position: relative;
}
If you drag the marker to the right, it leaves visible area of the map.
How can I prevent the user from dragging the marker outside the map ?
Thanks !
answering my own question in case it helps anyone.
We detect the map container size and check if the marker is going outside the visible area by converting its lat/lng coordinates to a container point (map.containerPointToLatLng(markerContainerPosition))
As a bonus, this code leaves the marker in the same position relative to the map container when the user moves the map. It ensures that the marker never goes outside the visible area (even when zooming)
var southWest = L.latLng(-90, -180),
northEast = L.latLng(90, 180);
var bounds = L.latLngBounds(southWest, northEast);
var map = L.map('map', {
minZoom: 2,
zoomControl: false,
attributionControl: false,
maxBounds: bounds
});
// Using cartoDB basemap
L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png', {
minZoom: 2,
subdomains: 'abcd',
detectRetina: true,
attribution: ''
}).addTo(map);
map.fitBounds(bounds);
var newMarker0 = L.marker(map.getCenter(), {
icon: new L.Icon.Default(),
zIndexOffset: 10000,
draggable: true
});
newMarker0.addTo(map);
var mapSize = map.getSize();
var markerContainerPosition = map.latLngToContainerPoint(newMarker0.getLatLng());
function mapMove() {
newMarker0.setLatLng(map.containerPointToLatLng(markerContainerPosition));
}
function markerDrag(e) {
var mTempContainerPos = map.latLngToContainerPoint(newMarker0.getLatLng());
var newPos;
if (mTempContainerPos.x < 20) {
if (mTempContainerPos.y < 45) {
newPos = L.point(20, 45);
} else if (mTempContainerPos.y > (mapSize.y - 20)) {
newPos = L.point(20, mapSize.y - 20);
} else {
newPos = L.point(20, mTempContainerPos.y);
}
} else if (mTempContainerPos.x > mapSize.x - 20) {
if (mTempContainerPos.y < 45) {
newPos = L.point(mapSize.x - 20, 45);
} else if (mTempContainerPos.y > (mapSize.y - 20)) {
newPos = L.point(mapSize.x - 20, mapSize.y - 20);
} else {
newPos = L.point(mapSize.x - 20, mTempContainerPos.y);
}
} else {
if (mTempContainerPos.y < 45) {
newPos = L.point(mTempContainerPos.x, 45);
} else if (mTempContainerPos.y > (mapSize.y - 20)) {
newPos = L.point(mTempContainerPos.x, mapSize.y - 20);
}
}
if (newPos) {
markerContainerPosition = newPos;
newMarker0.setLatLng(map.containerPointToLatLng(newPos));
} else {
markerContainerPosition = mTempContainerPos;
}
}
map.on('move', mapMove);
newMarker0.on('drag', markerDrag);
A solution with slightly more generic code and tailored to dragging the marker rather than the map, but derivative of #Franckl's:
onMarkerDrag: function (event) {
// keep dragged marker within map bounds
var containerPoint = this.map.latLngToContainerPoint(event.target.getLatLng()),
clampX = null,
clampY = null,
MARKER_MARGIN = 10;
if (containerPoint.x - MARKER_MARGIN < 0) {
clampX = MARKER_MARGIN;
} else if (containerPoint.x + MARKER_MARGIN > this.mapContainerBounds.width) {
clampX = this.mapContainerBounds.width - MARKER_MARGIN;
}
if (containerPoint.y - MARKER_MARGIN < 0) {
clampY = MARKER_MARGIN;
} else if (containerPoint.y + MARKER_MARGIN > this.mapContainerBounds.height) {
clampY = this.mapContainerBounds.height - MARKER_MARGIN;
}
if (clampX !== null || clampY !== null) {
if (clampX !== null) { containerPoint.x = clampX; }
if (clampY !== null) { containerPoint.y = clampY; }
marker.setLatLng(this.map.containerPointToLatLng(containerPoint));
}
},
I derive this.mapContainerBounds once on map init instead of every time the drag handler fires (my map does not change size), like this:
this.mapContainerBounds = mapDOMNode.getBoundingClientRect();

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

Integrating / adding Google Earth View to my map

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.