I am trying new to localStorage, and I am trying to save the markers that the user can create on the map.
I created this function to place markers and delete them:
var redmarker = L.icon({
iconUrl: 'http://icons.iconarchive.com/icons/paomedia/small-n-flat/48/map-marker-icon.png',
iconSize: [48, 48], // size of the icon
iconAnchor: [24, 48], // point of the icon which will correspond to marker's location
popupAnchor: [-2, -48] // point from which the popup should open relative to the iconAnchor
});
var popup = L.popup();
// On map click shows coordinates X, Y
function onMapClick(e) {
var geojsonFeature = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [e.latlng.lat, e.latlng.lng]
}
}
var marker;
L.geoJson(geojsonFeature, {
pointToLayer: function(feature, latlng){
marker = L.marker(e.latlng, {
title: "Resource Location",
alt: "Resource Location",
riseOnHover: true,
draggable: true,
icon: redmarker
}).bindPopup("<<span>X: " + e.latlng.lng + ", Y: " + e.latlng.lat + "</span><br><a href='#' id='marker-delete-button'>Delete marker</a>");
marker.on("popupopen", onPopupOpen);
return marker;
}
}).addTo(map);
}
function onPopupOpen() {
var tempMarker = this;
$("#marker-delete-button:visible").click(function () {
map.removeLayer(tempMarker);
});
}
map.on('click', onMapClick);
I am not familiar with localStorage, this is new to me. Also I am trying to make the popup editable, an user input there for the user name the marker.
I saw this example of input:
http://tahvel.info/simpleStorage/example/
Something like that.
A working example of my function: http://fiddle.jshell.net/2g4h5eu5/1/
Can someone help me save the markers in localStorage?
Also my problem is that I don't know what render's the markers on leaflet after I click, so I don't know exactly what I need to save in local storage to retrieve those markers.
you can use the following functions to manage your localStorage
localStorage.setItem('favoriteflavor','vanilla');
var taste = localStorage.getItem('favoriteflavor');
// -> "vanilla"
localStorage.removeItem('favoriteflavor');
var taste = localStorage.getItem('favoriteflavor');
// -> null
check this link
also you can use jQuery Storage API plugin to make things more cross-browser
http://fiddle.jshell.net/thesane/2g4h5eu5/29/
/// Load markers
function loadMarkers()
{
var markers = localStorage.getItem("markers");
if(!markers) return;
markers = JSON.parse(markers);
markers.forEach(function(entry) {
latlng = JSON.parse(entry);
var geojsonFeature = {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [latlng.lat, latlng.lng]
}
}
var marker;
L.geoJson(geojsonFeature, {
pointToLayer: function(feature){
marker = L.marker(latlng, {
title: "Resource Location",
alt: "Resource Location",
riseOnHover: true,
draggable: true,
icon: redmarker
}).bindPopup("<<span>X: " + latlng.lng + ", Y: " + latlng.lat + "</span><br><a href='#' id='marker-delete-button'>Delete marker</a>");
marker.on("popupopen", onPopupOpen);
return marker;
}
}).addTo(map);
});
}
/// Store markers
function storeMarker(marker)
{
var markers = localStorage.getItem("markers");
if(!markers) {
markers = new Array();
console.log(marker);
markers.push(JSON.stringify(marker));
}
else
{
markers = JSON.parse(markers);
markers.push(JSON.stringify(marker));
}
console.log(JSON.stringify(markers));
localStorage.setItem('markers', JSON.stringify(markers));
}
// Delete Marker
function deleteMarker(lng, lat) {
var markers = localStorage.getItem("markers");
markers = JSON.parse(markers);
for(var i=0;i<markers.length;i++){
latlng = JSON.parse(markers[i]);
if(latlng.lat == lat && latlng.lng == lng)
{
markers.splice(i,1);
}
}
localStorage.setItem('markers', JSON.stringify(markers));
}
Related
I'm trying to make a web app that uses leaflet to display a map, users should be able to draw and edit polygons over the map and they should have the ability to name each polygon they create.
I want to open a popup when a polygon is created that asks for a name and then set it to a property in a geojson feature.
I tried to follow this example Leaflet popup form but I couldn't get it to work with the leaflet draw created event.
Here's what I got.
// Map center
var center = [-32.692825, -62.104689];
// Map creation
var map = L.map('map').setView(center, 14);
// Map tile layer
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
// Initialise the FeatureGroup to store editable layers
var editableLayers = new L.FeatureGroup();
map.addLayer(editableLayers);
// Draw plugin options
var drawPluginOptions = {
position: 'topleft',
draw: {
polygon: {
allowIntersection: false, // Restricts shapes to simple polygons
drawError: {
color: '#e1e100', // Color the shape will turn when intersects
message: '<strong>Oh snap!<strong> you can\'t draw that!' // Message that will show when intersect
},
shapeOptions: {
color: '#97009c'
}
},
// disable toolbar item by setting it to false
polyline: false,
circle: false, // Turns off this drawing tool
rectangle: false,
marker: false,
},
edit: {
featureGroup: editableLayers,
polygon: {
allowIntersection: false
} //REQUIRED!!
}
};
// Initialise the draw control and pass it the FeatureGroup of editable layers
var drawControl = new L.Control.Draw(drawPluginOptions);
map.addControl(drawControl);
var editableLayers = new L.FeatureGroup();
map.addLayer(editableLayers);
// draw created event handler
function polygonCreateHandler(e) {
var type = e.layerType;
var layer = e.layer;
if (type != 'polygon') {
alert("ESTO NO ES UN POLIGONO");
return;
}
editableLayers.addLayer(layer);
}
// draw created event
map.on('draw:created', function(e) {
polygonCreateHandler(e);
});
//Ignore this
/*jshint multistr: true */
var template = '<form id="popup-form">\
<label for="input-speed">New speed:</label>\
<input id="input-speed" class="popup-input" type="number" />\
<button id="button-submit" type="button">Save Changes</button>\
</form>';
/*
** fetch geojson example
let geojson_url = "https://raw.githubusercontent.com/delineas/leaflet-flyto-webpack-bulma/master/src/data/arboles_singulares_en_espacios_naturales.geojson"
fetch(
geojson_url
).then(
res => res.json()
).then(
data => {
let geojsonlayer = L.geoJson(data, {
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties['arbol_nombre'])
layer.setIcon(treeMarker)
}
}).addTo(map)
map.fitBounds(geojsonlayer.getBounds())
}
)
** layer polygon example
var geojson_msjz_polygon = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "name": "Test Distrito electoral"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-62.103266716003425,
-32.687209099455636
],
[
-62.13047504425048,
-32.68211618935444
],
[
-62.133564949035645,
-32.693746380985395
],
[
-62.106142044067376,
-32.698838627713116
],
[
-62.103266716003425,
-32.687209099455636
]
]
]
}
}
]
};
let geojsonlayer = L.geoJson(geojson_msjz_polygon, {
onEachFeature: function(feature, layer) {
let text = L.tooltip({
permanent: true,
direction: 'center',
className: 'text'
})
.setContent(feature.properties.name)
.setLatLng(layer.getBounds().getCenter());
text.addTo(map);
}
}).addTo(map);
map.fitBounds(geojsonlayer.getBounds())
*/
#map {
height: 98vh;
width: 100hw;
}
body {
margin: 0;
}
html,
body,
#leaflet {
height: 100%;
}
.popup-table {
width: 100%;
}
.popup-table-row {
background-color: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.2.3/leaflet.draw.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.2.3/leaflet.draw.css" rel="stylesheet" />
<div id="map"></div>
Just bind a popup on the created layer and open it once it is created
function polygonCreateHandler(e) {
var type = e.layerType;
var layer = e.layer;
if (type != 'polygon') {
alert("ESTO NO ES UN POLIGONO");
return;
}
editableLayers.addLayer(layer);
layer.bindPopup(template).openPopup(); // here create and open the popup with your form
}
// Map center
var center = [-32.692825, -62.104689];
// Map creation
var map = L.map('map').setView(center, 14);
// Map tile layer
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
// Initialise the FeatureGroup to store editable layers
var editableLayers = new L.FeatureGroup();
map.addLayer(editableLayers);
// Draw plugin options
var drawPluginOptions = {
position: 'topleft',
draw: {
polygon: {
allowIntersection: false, // Restricts shapes to simple polygons
drawError: {
color: '#e1e100', // Color the shape will turn when intersects
message: '<strong>Oh snap!<strong> you can\'t draw that!' // Message that will show when intersect
},
shapeOptions: {
color: '#97009c'
}
},
// disable toolbar item by setting it to false
polyline: false,
circle: false, // Turns off this drawing tool
rectangle: false,
marker: false,
},
edit: {
featureGroup: editableLayers,
polygon: {
allowIntersection: false
} //REQUIRED!!
}
};
// Initialise the draw control and pass it the FeatureGroup of editable layers
var drawControl = new L.Control.Draw(drawPluginOptions);
map.addControl(drawControl);
var editableLayers = new L.FeatureGroup();
map.addLayer(editableLayers);
var template = '<form id="popup-form">\
<label for="input-speed">New speed:</label>\
<input id="input-speed" class="popup-input" type="number" />\
<button id="button-submit" type="button">Save Changes</button>\
</form>';
var createdPolygonTemplate = '<form id="popup-form">\
<label for="input-speed">Name:</label>\
<input id="name" type="text" />\
</form>';
// draw created event handler
function polygonCreateHandler(e) {
var type = e.layerType;
var layer = e.layer;
if (type != 'polygon') {
alert("ESTO NO ES UN POLIGONO");
return;
}
editableLayers.addLayer(layer);
layer.bindPopup(createdPolygonTemplate).openPopup()
}
// draw created event
map.on('draw:created', function(e) {
polygonCreateHandler(e);
});
//Ignore this
/*jshint multistr: true */
/*
** fetch geojson example
let geojson_url = "https://raw.githubusercontent.com/delineas/leaflet-flyto-webpack-bulma/master/src/data/arboles_singulares_en_espacios_naturales.geojson"
fetch(
geojson_url
).then(
res => res.json()
).then(
data => {
let geojsonlayer = L.geoJson(data, {
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties['arbol_nombre'])
layer.setIcon(treeMarker)
}
}).addTo(map)
map.fitBounds(geojsonlayer.getBounds())
}
)
** layer polygon example
var geojson_msjz_polygon = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "name": "Test Distrito electoral"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-62.103266716003425,
-32.687209099455636
],
[
-62.13047504425048,
-32.68211618935444
],
[
-62.133564949035645,
-32.693746380985395
],
[
-62.106142044067376,
-32.698838627713116
],
[
-62.103266716003425,
-32.687209099455636
]
]
]
}
}
]
};
let geojsonlayer = L.geoJson(geojson_msjz_polygon, {
onEachFeature: function(feature, layer) {
let text = L.tooltip({
permanent: true,
direction: 'center',
className: 'text'
})
.setContent(feature.properties.name)
.setLatLng(layer.getBounds().getCenter());
text.addTo(map);
}
}).addTo(map);
map.fitBounds(geojsonlayer.getBounds())
*/
#map {
height: 98vh;
width: 100hw;
}
body {
margin: 0;
}
html,
body,
#leaflet {
height: 100%;
}
.popup-table {
width: 100%;
}
.popup-table-row {
background-color: grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.0-beta.2.rc.2/leaflet.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.2.3/leaflet.draw.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.2.3/leaflet.draw.css" rel="stylesheet" />
<div id="map"></div>
Yes, the next is a code example:
<div id="map" style="width: 100%; height: 500px;"></div>
<script>
var map = L.map('map', {
center: [18.9, -71.2],
zoom: 8,
});
const tileURL = 'https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png'
L.tileLayer(tileURL).addTo(map);
drawnItems = L.featureGroup().addTo(map);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: drawnItems,
},
});
var getName = function(layer) {
var name = prompt('please, enter the geometry name', 'geometry name');
return name;
};
map.addControl(drawControl);
map.on(L.Draw.Event.CREATED, function(e) {
var layer = e.layer;
var name = getName(layer);
if (name == 'geometry name') {
layer.bindPopup('-- no name provided --');
} else if (name == '') {
layer.bindPopup('-- no name provided --');
} else {
layer.bindTooltip(name, {permanent:true, direction:'top'})
};
drawnItems.addLayer(layer);
});
</script>
And this is the result:
enter image description here
Do not forget the cdn's:
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw-src.css" integrity="sha512-vJfMKRRm4c4UupyPwGUZI8U651mSzbmmPgR3sdE3LcwBPsdGeARvUM5EcSTg34DK8YIRiIo+oJwNfZPMKEQyug==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.js" integrity="sha512-ozq8xQKq6urvuU6jNgkfqAmT7jKN2XumbrX1JiB3TnF7tI48DPI4Gy1GXKD/V3EExgAs1V+pRO7vwtS1LHg0Gw==" crossorigin="anonymous"></script>
Pardon me if this question is silly. I've got an array in an object that I need to add to a map. I know it needs a for loop (likely in the object) to access the additional properties in the array. Only the last indexed value is shown on the map when I execute the code. Thanks in advance for your help.
var map = L.map('map', {
center: [29.940125, -90.08346],
zoom: 13
});
// Get basemap URL from Leaflet Providers
var basemap_url = 'http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png'
// Get basemap attributes from Leaflet Providers
var basemap_attributes = {
maxZoom: 18,
attribution: '© OpenStreetMap'
};
// requests some map tiles
var tiles = L.tileLayer(basemap_url, basemap_attributes);
map.addLayer(tiles);
var i = 0
// declare hotspots object
var hotspots = [{
name: "Mariza",
properties: {
description: "Italian-inspired fare dished out in an airy loft building with an industrial-chic vibe.",
coordinates: [29.9629337, -90.0501008],
url: 'http://marizaneworleans.com/',
phone: '(504) 598-5700',
icon: 'svgs/restaurant-15.svg'
},
name: "Tipitina's",
properties: {
description: "Founded as a clubhouse for Professor Longhair, Tip's has played host to NOLA music legends since opening its doors in 1977.",
coordinates: [29.917284, -90.042986],
url: 'https://www.tipitinas.com//',
phone: '(504) 895-8477',
icon: 'svgs/music-15.svg'
},
name: "Euclid Records New Orleans",
properties: {
description: "We’re 4000 square feet of boss vinyl both new and used.",
coordinates: [29.962066, -90.042970],
url: 'https://euclidnola.com/',
phone: '(504) 947-4348',
icon: 'svgs/music-11.svg'
}
}];
// declare variable for accessing object properties
var props = hotspots[i].properties;
var icon = L.icon({
iconUrl: props.icon,
iconSize: [40, 40],
popupAnchor: [0, -22],
className: "icon"
});
var popup = `<h3>${hotspots[i].name}</h3>
<p>${props.description}</p>
<p><b>website</b>: <a href='${props.url}'>${props.url}</a></p>
<p><b>phone</b>: ${props.phone}</p>`
var marker = L.marker(hotspots[i].properties.coordinates, {
icon: icon
})
.addTo(map)
.bindPopup(popup);
marker.on("mouseover", function () {
this.openPopup();
});
marker.on("mouseout", function () {
this.closePopup();
});
You need a for loop in order to iterate over all the hotspots and add them to the map:
var map = L.map('map', {
center: [29.940125, -90.08346],
zoom: 13
});
// Get basemap URL from Leaflet Providers
var basemap_url = 'http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png'
// Get basemap attributes from Leaflet Providers
var basemap_attributes = {
maxZoom: 18,
attribution: '© OpenStreetMap'
};
// requests some map tiles
var tiles = L.tileLayer(basemap_url, basemap_attributes);
map.addLayer(tiles);
// declare hotspots object
var hotspots = [{
name: "Mariza",
properties: {
description: "Italian-inspired fare dished out in an airy loft building with an industrial-chic vibe.",
coordinates: [29.9629337, -90.0501008],
url: 'http://marizaneworleans.com/',
phone: '(504) 598-5700',
icon: 'svgs/restaurant-15.svg'
},
name: "Tipitina's",
properties: {
description: "Founded as a clubhouse for Professor Longhair, Tip's has played host to NOLA music legends since opening its doors in 1977.",
coordinates: [29.917284, -90.042986],
url: 'https://www.tipitinas.com//',
phone: '(504) 895-8477',
icon: 'svgs/music-15.svg'
},
name: "Euclid Records New Orleans",
properties: {
description: "We’re 4000 square feet of boss vinyl both new and used.",
coordinates: [29.962066, -90.042970],
url: 'https://euclidnola.com/',
phone: '(504) 947-4348',
icon: 'svgs/music-11.svg'
}
}];
//// LOOP GOES HERE: ////
for ( let i = 0; i < hotspots.length; i++ ){
// declare variable for accessing object properties
let props = hotspots[i].properties;
let icon = L.icon({
iconUrl: props.icon,
iconSize: [40, 40],
popupAnchor: [0, -22],
className: "icon"
});
let popup = `<h3>${hotspots[i].name}</h3>
<p>${props.description}</p>
<p><b>website</b>: <a href='${props.url}'>${props.url}</a></p>
<p><b>phone</b>: ${props.phone}</p>`
let marker = L.marker(hotspots[i].properties.coordinates, {
icon: icon
})
.addTo(map)
.bindPopup(popup);
marker.on("mouseover", function() {
this.openPopup();
});
marker.on("mouseout", function() {
this.closePopup();
});
}
There isn't a loop anywhere, so i is always going to be 0
Put it in a for-loop?
for(var i = 0; i < hotspots.length; i++) {
var props = hotspots[i].properties;
var icon = L.icon({
iconUrl: props.icon,
iconSize: [40, 40],
popupAnchor: [0, -22],
className: "icon"
});
var popup = `<h3>${hotspots[i].name}</h3>
<p>${props.description}</p>
<p><b>website</b>: <a href='${props.url}'>${props.url}</a></p>
<p><b>phone</b>: ${props.phone}</p>`
var marker = L.marker(hotspots[i].properties.coordinates, {
icon: icon
})
.addTo(map)
.bindPopup(popup);
}
//Final Code
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: [0, 0],
zoom: 3
})
});
// -- GeoJSON layer --
// Define a GeoJSON source that will load features via a http call. By
// specifying the projection of the map's view OL3 will transform the coordinates
// for display
var planningAppsSource = new ol.source.GeoJSON({
'projection': map.getView().getProjection(),
'url': 'http://localhost/osgis-ol3-leaflet-master/ol3/data.geojson'
});
// Create a vector layer to display the features within the GeoJSON source and
// applies a simple icon style to all features
var planningAppsLayer = new ol.layer.Vector({
source: planningAppsSource,
style: new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 40],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'marker-icon.png'
}))
})
});
// Add the layer to the map
map.addLayer(planningAppsLayer);
var input = document.getElementById('input-airports');
map.on('click', function(evt) {
var feature = map.forEachFeatureAtPixel(
evt.pixel, function(ft, l) { return ft; });
if (feature) {
console.log(feature.getProperties());
input.value = feature.get('desc');
}
});
map.on('pointermove', function(e) {
if (e.dragging) return;
var hit = map.hasFeatureAtPixel(map.getEventPixel(e.originalEvent));
});
I succeed creating a simple map with OL3 with static markers pointing airports which take them data in an external JSON file.
But now i would like that when i click on a marker, create a function which find the name of the airport corresponding to the marker, in my JSON file and show it in an external field type:input.
I already tried to create a click event on my marker, an open layers interaction, try to take back some data in my Json File. but it seems like i'm missing something, all my little parts doesn't fit all together.
I don't know where i can start :s
Thank you all for your answers.
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: [0, 0],
zoom: 3
})
});
// -- GeoJSON layer --
// Define a GeoJSON source that will load features via a http call. By
// specifying the projection of the map's view OL3 will transform the coordinates
// for display
var planningAppsSource = new ol.source.GeoJSON({
'projection': map.getView().getProjection(),
'url': 'http://localhost/osgis-ol3-leaflet-master/ol3/data.geojson'
});
// Create a vector layer to display the features within the GeoJSON source and
// applies a simple icon style to all features
var planningAppsLayer = new ol.layer.Vector({
source: planningAppsSource,
style: new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 40],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
src: 'marker-icon.png'
}))
})
});
// Add the layer to the map
map.addLayer(planningAppsLayer);
// Map Click event
planningAppsSource.addEventListener(map, 'click', function(event){
var getHttpRequest = function () {
var httpRequest = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
httpRequest = new XMLHttpRequest();
if (httpRequest.overrideMimeType) {
httpRequest.overrideMimeType('text/xml');
}
}
else if (window.ActiveXObject) { // IE
try {
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!httpRequest) {
alert('Abandon :( Impossible de créer une instance XMLHTTP');
return false;
}
return httpRequest
}
});
GeoJSON:
{
"type": "FeatureCollection",
"features": [
{
"geometry": {
"type": "Point",
"coordinates": [
-145.494,
-17.3595
]
},
"type": "Feature",
"properties": {
"code": "AAA",
"lon": "-17.3595",
"lat": "-145.494",
"name": "Anaa Airport",
"city": "Anaa",
"state": "Tuamotu-Gambier",
"country": "French Polynesia",
"woeid": "12512819",
"tz": "Pacific\/Midway",
"phone": "",
"type": "Airports",
"email": "",
"url": "",
"runway_length": "4921",
"elev": "7",
"icao": "NTGA",
"direct_flights": "2",
"carriers": "1"
}
}
Just add these two listeners (and remove all that planningAppsSource.addEventListener stuff):
map.on('click', function(evt) {
var feature = map.forEachFeatureAtPixel(
evt.pixel, function(ft, l) { return ft; });
if (feature) {
// just to show all your feature's properties
console.log(feature.getProperties());
// to get a specific property
var name = feature.get('name');
var city = feature.get('city');
}
});
// you don't actually need this
// this is only to change the cursor to a pointer when is over a feature
map.on('pointermove', function(e) {
if (e.dragging) return;
var hit = map.hasFeatureAtPixel(map.getEventPixel(e.originalEvent));
map.getTargetElement().style.cursor = hit ? 'pointer' : '';
});
I am starting to use the Google Map Javascript API V3 and wish to display markers on a map, using GeoJSON. My GeoJSON is as follows:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [153.236112, -27.779627]
},
"properties": {
"name": "[153.236112, -27.779627]",
"description": "Timestamp: 16:37:16.293"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [153.230447, -27.777501]
},
"properties": {
"name": "[153.230447, -27.777501]",
"description": "Timestamp: 16:37:26.298"
}
}
]
}
And my JavaScript code to load the GeoJSON:
var map;
var marker;
function initialize() {
// Create a simple map.
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 14,
center: ${lastPosition}
});
// Load the associated GeoJSON
var url = 'fieldDataGeoJSON';
url += '?deviceId=' + deviceId + '&fieldId=' + fieldId;
map.data.loadGeoJson(url);
}
google.maps.event.addDomListener(window, 'load', initialize);
Note: the URL "fieldDataGeoJSON.." returns the GeoJSON, as you might have already figured out.
This works well: the markers are shown on the map, at the good location. But the fields "name" and "description" present in the GeoJSON are not linked to the markers, meaning that they are not displayed when I click on the marker.
I guess that the first question would be: "Is it supposed to be supported?". If not, does it mean that I have to parse the GeoJSON to add the names and descriptions? Do you have any hints on how to achieve this?
Thank you in advance for your help!
Normal Google Maps Javascript API v3 event listeners work, as do normal infowindows.
var map;
var infowindow = new google.maps.InfoWindow();
function initialize() {
// Create a simple map.
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 14,
center: new google.maps.LatLng(-27.779627,153.236112)
});
google.maps.event.addListener(map, 'click', function() {
infowindow.close();
});
// Load the associated GeoJSON
var url = 'http://www.geocodezip.com/fieldDataGeoJSON.txt';
map.data.loadGeoJson(url);
// Set event listener for each feature.
map.data.addListener('click', function(event) {
infowindow.setContent(event.feature.getProperty('name')+"<br>"+event.feature.getProperty('description'));
infowindow.setPosition(event.latLng);
infowindow.setOptions({pixelOffset: new google.maps.Size(0,-34)});
infowindow.open(map);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
working example
Currently, I am displaying 500-600 Markers on Google map, with their names as tooltip. Now,
I need to display the tool-tip of all overlapping markers as comma-separated i.e. Marker1, Marker2, Marker3 etc. if Marker1, Marker2, Marker3 are overlapped on map.
I found many other different examples on google map at internet especially at GeoCodeZip, but not of my requirement.
if this requirement is once filled, Am afraid of performance issues on zoom changed events, as tooltip needed to be updated (if overlapping is changed).
Update1 : I have already show Overlapping Marker spiderfier to client but not acceptable.
Does anyone have right path or working example ?
Thanks
-Anil
The core of this is to find the pixel distance between LatLngs. Then before adding each marker check the pixel distance between it and any existing markers. If there is another marker nearby add to the title otherwise create a new marker. jsFiddle
function init() {
var mapOptions = {
center: new google.maps.LatLng(0, -0),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
// to get the pixel position from the latlng
// https://stackoverflow.com/questions/1538681/how-to-call-fromlatlngtodivpixel-in-google-maps-api-v3
var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
google.maps.event.addListenerOnce(map, 'idle', function() {
if (overlay.getProjection()) {
var points = [
{ latlng: new google.maps.LatLng(40, -100), title: '1' },
{ latlng: new google.maps.LatLng(40.125, -100.125), title: '2' },
{ latlng: new google.maps.LatLng(40.25, -100.25), title: '3' },
{ latlng: new google.maps.LatLng(40.5, -100.5), title: '4' },
{ latlng: new google.maps.LatLng(40.75, -100.75), title: '5' },
{ latlng: new google.maps.LatLng(41, -101), title: '6' },
{ latlng: new google.maps.LatLng(35, -95), title: '7' },
{ latlng: new google.maps.LatLng(45, 105), title: '8' },
{ latlng: new google.maps.LatLng(25, -115), title: '9' },
{ latlng: new google.maps.LatLng(55, -85), title: '10' },
{ latlng: new google.maps.LatLng(30, -34), title: '11' }
];
// for each point
var markers = [];
points.forEach(function (point) {
var nearby = false;
var pointPixelPosition = overlay.getProjection().fromLatLngToContainerPixel(point.latlng);
markers.forEach(function(marker) {
var markerPixelPosition = overlay.getProjection().fromLatLngToContainerPixel(marker.getPosition());
// check for marker 'near by'
if (Math.abs(pointPixelPosition.x - markerPixelPosition.x) < 10 || Math.abs(pointPixelPosition.y - markerPixelPosition.y) < 10) {
nearby = true;
marker.setTitle(marker.getTitle() + ', ' + point.title);
}
});
// create new marker
if (!nearby) {
markers.push(new google.maps.Marker({ map: map, position: point.latlng, title: point.title }));
}
});
}
map.setCenter(new google.maps.LatLng(39.8282, -98.5795));
});
}