I am working with leaflet api where user can put markers on map. I have made a custom button for putting marker.
I am willing to draw line between those markers i.e. using
L.polylines() but as I am new to javascript and leaflet I can't
understand how to pass those latlng point to array which will later be
used in these functions. For initial working I have passed static
coordinates(working as req).
L.easyButton('fa-link', function () {
var secureThisArea = [[-81, 100.75], [-76.50, 245.75], [-145.50, 184.25], [-128, 311.75]];
map.on('click', function fencePlace(e) {
L.marker([-81, 100.75], { icon: fenceIcon, draggable: true }).bindPopup("this is first").addTo(map);
L.marker([-76.50, 245.75], { icon: fenceIcon, draggable: true }).bindPopup("this is second").addTo(map);
L.marker([-145.50, 184.25], { icon: fenceIcon, draggable: true }).bindPopup("this is third").addTo(map);
L.marker([-128, 311.75], { icon: fenceIcon, draggable: true }).bindPopup("this is fourth").addTo(map);
L.polyline(secureThisArea).addTo(map);
});
}).addTo(map);
Adding another value to an array is easy, e.g.:
secureThisArea.push([-81, 100.75]);
You can find more details (also about anything else JavaScript related) at Mozilla Developer Network.
If you want to use the coordinates from the marker objects, you can get those with:
var myMarker = L.marker([-81, 100.75], { icon: fenceIcon, draggable: true }),
latLng = null;
latLng = myMarker.getLatLng();
Also take a look at the Leaflet documentation.
If i understand you correctly you want to create markers on click and connect them via polylines. That's easy to do, in code with comments to explain:
// Create new empty polyline and add it to the map
var polyline = new L.Polyline([]).addTo(map);
// Handle map click event
map.on('click', function(event) {
// New marker on coordinate, add it to the map
new L.Marker(event.latlng).addTo(map);
// Add coordinate to the polyline
polyline.addLatLng(event.latlng);
});
Now afterwards if you want to get all the coordinates added to the polyline you can use the getLatLngs method of L.Polyline which returns an array of L.LatLng objects.
Reference: http://leafletjs.com/reference.html#polyline
Example: http://plnkr.co/edit/h7aMwc?p=preview
Related
I'm using MarkerClusterer with google maps api, I'm trying to change the behavior of the markers with the renderer inerface, as they explain in the doc : https://googlemaps.github.io/js-markerclusterer
problem is, I don't understand the doc... it says that the MarkerClusterer class can accept parameters :
{
algorithm?: Algorithm;
map?: google.maps.Map;
markers?: google.maps.Marker[];
renderer?: Renderer;
onClusterClick?: onClusterClickHandler;
}
and indeed I can see it in the source code : https://github.com/googlemaps/js-markerclusterer/blob/1ee6469fa3c62a30c39cf509b379847741a7ebb9/src/markerclusterer.ts
and I can see here the implementation of DefaultRenderer, the default value for the renderer parameter : https://github.com/googlemaps/js-markerclusterer/blob/1ee6469fa3c62a30c39cf509b379847741a7ebb9/src/renderer.ts
so in my code, I thought I should create an object with a method called render that returns a new google.maps.Marker. I tried lots of different variations, I show you one there, in which I took the source code with few modifications (colors of markerclusters), I don't know what I should actually do to make it works :
function init_map() {
let map = new google.maps.Map(document.getElementById("ljdp_map"), { zoom: 2, center: {lat:46.227638, lng:2.213749} });
let markers = [];
for (ev of events) // events is defined outside this function
markers.push( new google.maps.Marker({ position: ev.coordinates, map: map }) );
// so, this is where I try to modify the cluster appearance, without luck
// maybe "my_renderer" need to be a class inheriting from DefaultRenderer ?
// class my_renderer extends markerClusterer.DefaultRenderer {
// it didn't work
let my_renderer = {
render({ count, position }, stats) {
const svg = window.btoa(`
<svg fill="#00ff00" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240">
<circle cx="120" cy="120" opacity=".6" r="70" /></svg>`);
return new google.maps.Marker({
position,
icon: {
url: `data:image/svg+xml;base64,${svg}`,
scaledSize: new google.maps.Size(45, 45),
},
title: `Cluster of ${count} markers`,
zIndex: Number(google.maps.Marker.MAX_ZINDEX) + count,
});
}
}
// since the render argument is the fourth, after an algorithm argument, in the constructor,
// maybe I need to create an algorithm object to place the renderer at the right position ?
// let algorithm = new markerClusterer.SuperClusterAlgorithm({});
// new markerClusterer.MarkerClusterer({ map, markers, algorithm, my_renderer });
// it didn't work
new markerClusterer.MarkerClusterer({ map, markers, my_renderer });
}
the init function is called with :
<script src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=ini_map"></script>
and the marker clustering library is added by this script :
<script src="https://unpkg.com/#googlemaps/markerclusterer/dist/index.min.js"></script>
and the output is as if I didn't add my_renderer, cluster are not personalized. I don't know if I'm on the right way but making mistakes, or if it's not the way intended to modify the clusters ?
so, looking at this other SO post : Google Maps markerClusterer: how to combine Interface Renderer and GridOptions gridSize in configuration object?
I found what didn't work : the parameter name has to be exactly renderer and not my_renderer (that explains why the order in parameters didn't matters)
but I don't know why, maybe it's a typescript thing (I don't know typescript yet) ? I don't see it when I look at the source code, but there are lots of things I don't understand there anyway
the working code is the same, except for the object name :
function init_map() {
let map = new google.maps.Map(document.getElementById("ljdp_map"), { zoom: 2, center: {lat:46.227638, lng:2.213749} });
let markers = [];
for (ev of events) // events is defined outside this function
markers.push( new google.maps.Marker({ position: ev.coordinates, map: map }) );
// this is where the error was : the object has to be named exactly 'renderer'
let renderer = {
render({ count, position }, stats) {
const svg = window.btoa(`
<svg fill="#00ff00" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240">
<circle cx="120" cy="120" opacity=".6" r="70" /></svg>`);
return new google.maps.Marker({
position,
icon: {
url: `data:image/svg+xml;base64,${svg}`,
scaledSize: new google.maps.Size(45, 45),
},
title: `Cluster of ${count} markers`,
zIndex: Number(google.maps.Marker.MAX_ZINDEX) + count,
});
}
}
new markerClusterer.MarkerClusterer({ map, markers, renderer });
}
I don't know why :/
(I'll mark my answer as the solution for the moment, since it works, even though I don't have the explanation why)
I'm trying to create some markers to add using the Google Maps API, but if I try to specify an icon, I get the error: "constructor Error cannot be invoked without 'new'".
I'm running this via locahost.
Things I have tried:
Creating the marker, then setting the icon afterwards.
Different versions of the API.
Plugging my API key into the JSFiddle. (No errors.)
Removing/commenting out the icon lines. (Runs fine with the default icon.)
The code is pretty much verbatim from the Google-supplied JSFiddle for this, and it works there, but not on the page I'm working on.
const latlng = new google.maps.LatLng(this.location[0], this.location[1]);
this.marker = new google.maps.Marker({
position: latlng,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 10
},
draggable: false
});
I should have a circle icon at the specified position, but instead I get the following:
js?v=weekly&key=(APIKEY):53 Uncaught TypeError: Class constructor Error cannot be invoked without 'new'
at new Yc (:53)
at Object._.$c (:53)
at :56
at :56
at :56
at _.nf.setIcon (:66)
at .nf..T.setValues (:165)
at _.nf.mf [as constructor] (:79)
at new _.nf (:79)
at User.createMarker (classes.js:329)
It looks to me like there's a problem in the API's code that's making it difficult to debug the actual problem that's triggering the error.
Any suggestions would be appreciated.
Did you place the place in a class? I changed the official JSFiddle to use a class and it works.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {
lat: -25.363882,
lng: 131.044922
}
});
var Location = class Location {
constructor(lat, lng) {
this.location = [lat, lng]
const latlng = new google.maps.LatLng(this.location[0], this.location[1]);
this.marker = new google.maps.Marker({
position: latlng,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 10
},
draggable: false
});
this.marker.setMap(map);
}
}
var location = new Location(-25.363882, 131.044922);
}
What's happening is that the API is calling on a global Error object within the setIcon chain of functions (despite, apparently, a total lack of errors), which was causing an error due to me having overridden it with a custom Error class I had naively tried to add to the project.
Info on Error:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
This question already has answers here:
Google Map API - Removing Markers
(5 answers)
Closed 3 years ago.
I'm creating an application which gets the real-time location and renders to Google Map. After a specific time interval, I have to remove old markers and need to render the udpated markers.
Below is my code
function initMap(rtl_data) {
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
var latlng = new google.maps.LatLng(24.238162, 45.156379);
var myOptions = {
zoom: 7,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var marker = []
var map = new google.maps.Map(document.getElementById("map"),myOptions);
directionsDisplay.setMap(map);
makeMarkers(rtl_data)
function makeMarkers(rtl_data){
// Drivers Location Markers
deleteMarkers()
features = []
marker = []
drivers_latlng = rtl_data.drivers_latest_location
drivers_latlng.forEach(function(e){
features.push({
position: new google.maps.LatLng(e.lat, e.lng),
type: e.order_id,
title: e.driver_id,
description: e.order_id ? "Ongoing order: "+e.order_id : "No order assigned."
})
})
image = "/files/truck.png"
infoWindow = new google.maps.InfoWindow();
for (i = 0; i < features.length; i++) {
marker = new google.maps.Marker({
position: features[i].position,
map: map,
title: features[i].title,
type: features[i].type,
icon: image,
description: features[i].description
});
//Attach click event to the marker.
(function (marker) {
google.maps.event.addListener(marker, "click", function (e) {
//Wrap the content inside an HTML DIV in order to set height and width of InfoWindow.
infoWindow.setContent("<div style = 'width:200px;min-height:40px'>" + marker.description + "</div>");
infoWindow.open(map, marker);
});
})(marker);
}
// Sets the map on all markers in the array.
function setMapOnAll(map) {
for (var i = 0; i < marker.length; i++) {
marker[i].setMap(map);
}
}
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
setMapOnAll(null);
console.log('clearMarkers')
}
// Shows any markers currently in the array.
function showMarkers() {
setMapOnAll(map);
}
// Deletes all markers in the array by removing references to them.
function deleteMarkers() {
console.log('deleteMarkers')
clearMarkers();
marker = [];
}
}
// Fetch Realtime using time interval
setInterval(function() {
frappe.call({ // Simple AJAX Call which returns locations and location realated data.
method: "get_drivers_locations",
async: false,
callback: function(r){
rtl_data = r.message
}
})
makeMarkers(rtl_data)
}, 5000);
I already used Method's which is used in the documentaion by Google Map.
Using ClearMarkers the old markers get cleared. But in my case it is not working.
When I run above code it displaying me both old and upadted markers.
See below screenshot which is repetating markers with updated locations.
You initialize marker as an array:
var marker = []
But later assign a Marker instance:
marker = new google.maps.Marker({...})
I didn't run your example, but I expect, that marker variable will contain not an array of markers, but the last created marker.
Try to do next:
rename marker variable to markers
implement addMarker function. This function should push a new marker to markers array
After reading below thread:
Google Map API - Removing Markers
I found the solution.
I created one array.
gmarkers = []
and pushed all my new markers in it.
gmarkers.push(marker)
To delete the markers I used the following function.
function setMapOnAll(map) {
for (var i = 0; i < gmarkers.length; i++) {
gmarkers[i].setMap(map);
}
}
Your closure bracket for the init function is wrong. If you look at the original documentation the init function is closed before the addmarker function. In your example it is closed just before the setInterval. So your setInterval probably can't even access the makeMarker function because this one is inside another function.
I am using OpenLayers and I want to get all values from Marker (ol.Feature).
You can see in docs it is possible to add any value to ol.Feature.
import Feature from 'ol/Feature';
import Polygon from 'ol/geom/Polygon';
import Point from 'ol/geom/Point';
var feature = new Feature({
geometry: new Polygon(polyCoords),
labelPoint: new Point(labelCoords),
name: 'My Polygon' // <--- CUSTOM VALUE
});
// get the polygon geometry
var poly = feature.getGeometry();
// Render the feature as a point using the coordinates from labelPoint
feature.setGeometryName('labelPoint');
// get the point geometry
var point = feature.getGeometry();
I have a click event on map and I want to get those values.
this.map.on('click', (args) => {
this.map.forEachFeatureAtPixel(args.pixel, (feature, layer) => {
// do something
console.log(feature.values_); // <---- SEEMS LIKE 'PRIVATE' prop
});
});
It looks like ol.Feature has no method for getting these values. Is there any 'nicer' solution than feature.values_ ?
You can get all properties using
feature.getProperties()
or if you just need one, you can do
feature.get('name')
So as the title says, I'm using React and trying to implement Google Maps with list of places fetched from Foursquare and display their markers. I'm not using any packages such as react-google-maps etc, just vanilla JS. The map loads just fine, the places are fetched BUT the markers show every now and then. When they do load, they point to correct location but they load rarely. I'm not sure what's wrong with my createMarkers function here:
// Initialize map
initMap = () => {
let map = new window.google.maps.Map(document.getElementById("map"), {
zoom: 14,
center: {lat: 45.5616873, lng: 18.6770196 }
});
this.createMarkers(map);
}
// The following function uses the places array to create an array of markers on initialize.
createMarkers = (map) => {
for (let i = 0; i < this.state.places.length; i++) {
// Get the position from the location array
let position = this.state.places[i].location;
let name = this.state.places[i].name;
let venueID = this.state.places[i].venueID;
// Create a marker per location, and put into markers array.
let marker = new window.google.maps.Marker({
position: position,
name: name,
animation: window.google.maps.Animation.DROP,
icon: this.state.defaultIcon,
venueID: venueID,
map: map
});
// Set state to save the marker to our array of markers.
this.setState((state) => ({
markers: [...state.markers, marker]
}))
}
}
// Create default marker icon
makeMarkerIcon(markerColor) {
const markerImage = new window.google.maps.Icon(
'http://chart.googleapis.com/chart?chst=d_map_spin&chld=1.15|0|'+ markerColor +
'|40|_|%E2%80%A2',
new window.google.maps.Size(21, 34),
new window.google.maps.Point(0, 0),
new window.google.maps.Point(10, 34),
new window.google.maps.Size(21,34)
);
return markerImage;
};
Any help would be much appreciated, as I'm still new to React and prone to beginner's mistakes.