The user insert the city of departure and destination in 2 text input, then click on the button to display on the Google Map 2 markers corresponding to the inserted cities and a Polyline between those 2 points.
Here is my code:
//Global array
var pathArray = [];
var cities = [ origin, destination ];
$('#button').on("click", function() {
reverseGeocodeCities(cities);
});
function reverseGeocodeCities(cities) {
$.each(cities, function(index, value) {
geocoder.geocode({'address': value}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
addMarkerCity(results[0].geometry.location);
}
});
});
//Create the polyline just after the loop.
addPolyline();
}
function addMarkerCity(cityPosition) {
var currentMarker = map.addMarker({
position: cityPosition
});
//Add the position of the marker into the global pathArray used by addPolylineCity function.
pathArray.push(currentMarker.getPosition());
}
function addPolylineCity() {
console.log(pathArray); //Display "[]" at the first click.
var polyline = map.drawPolyline({
path: pathArray,
});
I have 2 problems with this code: The first one is, when the user click once on the button, the markers are displayed well on the Google Map but not the polyline between the 2 markers. I have to click twice on the button to make the polyline visible. To create the polyline, I'm using the global array pathArray containing each markers position. It always display an empty array at the first click and then the proper position of the markers after the second click on the button.
The second problem is that I'm doing a simple symbol animation on the created polyline but the flow direction change time to time, if I want to do London to New York, the symbol should slide from London to New york and not the reverse (I removed this part for code simplicity). Please note that I'm using Gmaps wrapper to use Google Map features.
Thanks for your help if you know what I'm doing wrong with my code.
You are creating the polyline first and then the markers, so the polyline does not appear
if (pathArray.length == 2) {
addPolylineCity();
}; //hardcode
An example JSFiddle
Related
I'm working with leaflet js and I have an array in which i store my markers which are automatically added to the map after the location of the user has been obtained.
problem is that i want to add an onclick listener so that any marker that is clicked will run a function.
please help me out cuz i'm stuck right now.
//objects for markers
var allMarkers=[];
var AllMarkers = L.layerGroup(allMarkers);
var Allpoints=[{
"latitudes":9.4258946,"longitudes":-0.8842213, "names":"first", "eastings":556568, "northings":446445, "description": "aijaskj jnrkajra skjanjanek ", "elevations": 5668
},
{
"latitudes":9.4254946,"longitudes":-0.8812213, "names":"second"},
{
"latitudes":9.4054946,"longitudes":-0.8802213, "names":"third"},
{
"latitudes":9.4754946,"longitudes":-0.8712213, "names":"fourth"},
];
//automatically plot all previous markers
var point = L.point(9.2754946, -0.8912213);
q = 0;
while(q< Allpoints.length){
//create Marker here
_newMarker = L.marker(
[Allpoints[q].latitudes, Allpoints[q].longitudes],
{title: Allpoints[q].names,
riseOnHover: true,
} ).addTo(mymap);
allMarkers.push(_newMarker);
q++
}
//function to send back the details of the clicked marker to a paragraph in my index.htm
//PROBLEM
L.marker('click', markers, showMarkerDetails) //however the code immediately above does not work
function showMarkerDetails(){
$("#returnControlName").html(controlName);
$("#returnControlLocation").html(`${controlLat.toFixed(4)} , ${controlLong.toFixed(4)} `);
$("#returnControlEastings").html(controlEastings);
$("#returnControlName").html(controlNorthings);
$("#returnControlName").html(controlElevation);
$("#returnControlName").html(controlDescription);
}
With L.marker() you add new markers / points to the map, you can't add events like that to them. (L.marker('click', markers, showMarkerDetails) )
Change your code to:
//automatically plot all previous markers
var point = L.point(9.2754946, -0.8912213);
q = 0;
while(q< Allpoints.length){
//create Marker here
_newMarker = L.marker([Allpoints[q].latitudes, Allpoints[q].longitudes],
{title: Allpoints[q].names,
riseOnHover: true,
}).addTo(mymap);
_newMarker.informations = Allpoints[q]; // save the data to the marker to read it later out
_newMarker.on('click',showMarkerDetails); // add click event to the markers
allMarkers.push(_newMarker);
q++
}
function showMarkerDetails(e){
var layer = e.target // get the clicked marker
var infos = layer.informations;
console.log(infos.description);
$("#returnControlName").html(controlName);
$("#returnControlLocation").html(`${controlLat.toFixed(4)} , ${controlLong.toFixed(4)} `);
$("#returnControlEastings").html(controlEastings);
$("#returnControlName").html(controlNorthings);
$("#returnControlName").html(controlElevation);
$("#returnControlName").html(controlDescription);
}
This is related to a previous question: Leafletjs dynamically bound map to visible overlays.
I am now using the Leaflet.FeatureGroup.SubGroup plugin with the Leaflet.markercluster plugin. Trying to set map bound to all visible markers and marker clusters. I am using 3 co-ordinates to test:
[43.6425657, -79.38705569999999]
[43.7164673, -79.3395846]
[-41.3142772, 174.8135975]
This is the code so far:
var map = L.map("mapid");
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(map);
map.setView([43.6532, -79.3832], 2);
var parentGroup = L.markerClusterGroup().addTo(map),
consultingMarkers = L.featureGroup.subGroup(parentGroup).addTo(map),
otherMarkers = L.featureGroup.subGroup(parentGroup).addTo(map);
// subGroup1
L.marker([43.6425657, -79.38705569999999]).addTo(consultingMarkers);
L.marker([43.7164673, -79.3395846]).addTo(consultingMarkers);
// subGroup2
L.marker([-41.3142772, 174.8135975], {icon: otherIcon}).addTo(otherMarkers);
var overlays = {
'consulting': consultingMarkers,
'other': otherMarkers
};
L.control.layers(null, overlays, {
collapsed: false
}).addTo(map);
map.on('overlayadd overlayremove', function () {
var bounds = parentGroup.getBounds(),
southWest = bounds.getSouthWest();
// Fit bounds only if the Parent Group actually has some markers,
// i.e. it returns valid bounds.
if (southWest && !southWest.equals(bounds.getNorthEast())) {
map.fitBounds(parentGroup.getBounds());
}
});
So far, I am running into these problems:
Map does not bound to the [-41.3142772, 174.8135975] co-ordinate
Un-checking the "consulting" layer does not bound the map to the markers from the "other" layer which has the co-ordinate [-41.3142772, 174.8135975].
Update: it seems to have this bounding problem for single markers. I tried adding another marker co-ordinate [43.76089289999999, -79.4103427] which would be in the cluster. But if I remove "consulting" cluster and remove "other" layer. The map still does not bound to the last marker left on the map.
If I understand correctly, you are puzzled because when one of your SubGroups has only 1 marker, the map.fitBounds does not look to be executed?
In that case, that is simply the expected behaviour of the !southWest.equals(bounds.getNorthEast()) check: it avoids executing the next block when bounds represents a null area, i.e. there is 0 or 1 marker into it.
By replacing the check by bounds.isValid(), you avoid only the case when there is 0 marker, but in the case there is exactly 1 marker, it will allow executing the next block, therefore trying to fit bounds on a null area. In such case, Leaflet pans to that single marker and zooms to maxZoom.
map.on('overlayadd overlayremove', function () {
var bounds = parentGroup.getBounds();
if (bounds.isValid()) {
map.fitBounds(bounds);
}
});
Demo: https://jsfiddle.net/3v7hd2vx/355/
How do i change my center for google maps with a link and remove other markers? i have this code
https://jsfiddle.net/m9ugbc7h/
So, i need to create a link for example
Ventura
In this case the function must change google maps center to focus the "ventura" marker and hide the other markes and when the user clicks on
Dolphinaris
the zoom will change and will hide every other marker and show only the ones of Dolphinaris
Thanks in advance
Make map visible outside of jQuery(document).ready.
Create var markers = []; array.
When crating markers, add custom property name to it, and push marker into markers array:
var marker = new google.maps.Marker({
position: new google.maps.LatLng(21.0241839, -86.8148164),
map: map,
visible: true,
icon: ventura,
name: 'ventura',
});
markers.push(marker);
On click, invoke resetMap() function:
Ventura
Inside resetMap function, set center and zoom to map, iterate markers, matching them by custom property name - matched one set visible, others set to invisible.
function resetMap(lat, lon, zoom, name) {
var newPos = new google.maps.LatLng(lat, lon);
map.setCenter(newPos);
map.setZoom(zoom);
markers.forEach(function(marker) {
if(marker.get('name') == name)
{
console.log('match');
marker.setVisible(true);
}
else
{
marker.setVisible(false);
}
});
Working fiddle: https://jsfiddle.net/m9ugbc7h/1/
EDIT:
Question: "is there any way to change smoothly the zoom and coordinates?"
Yes, use method:
panTo(latLng:LatLng|LatLngLiteral)
Changes the center of the map to the given LatLng. If the change is
less than both the width and height of the map, the transition will be
smoothly animated.
https://developers.google.com/maps/documentation/javascript/reference?csw=1
EDIT 2:
Implementing panTo is easy:
map.panTo(newPos);
instead of:
map.centerTo(newPos);
but as I have faced a bit 'flickering' effect due to hide/show markers that are close on the map, I have added some delay in functions invocation + markers show/hide:
function resetMap(lat, lon, zoom, name) {
var newPos = new google.maps.LatLng(lat, lon);
$.when( map.setZoom(zoom) ).done(function(){
$.when( map.panTo(newPos)).done(function(){
setMarkerVisibility(name);
});
});
}
And showing matched marker is now executed with 300 ms delay:
function setMarkerVisibility(name){
markers.forEach(function(marker) {
console.log(marker.get('name'));
if(marker.get('name') == name)
{
setTimeout(function(){ marker.setVisible(true); }, 300);
}
else
{
marker.setVisible(false);
}
});
}
It looks a bit smoother like this.
Working fiddle: https://jsfiddle.net/m9ugbc7h/3/
This question is related to this question: Updating Leaflet Marker Position Every x Seconds with JSON. Only I want to project the map created with Leaflet onto a 3D globe with WebGLEarth. Normally you can combine Leaflet and WebGLEarth by replacing L.map, L.marker and so on with WE.map, WE.marker in your original Leaflet code.
I would like to have the current location of the International Space Station projected on my 3D globe, so I replaced the L.marker in the update_position function of this code...
var cloudmadeUrl = 'http://{s}.mqcdn.com/tiles/1.0.0/sat/{z}/{x}/{y}.jpg';
var subDomains = ['otile1','otile2','otile3','otile4'];
var cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 11, subdomains: subDomains});
var map = new L.Map('map', {layers : [cloudmade]}).fitWorld();
var iss;
function update_position() {
$.getJSON('http://open-notify-api.herokuapp.com/iss-now.json?callback=?', function(data) {
console.log(data);
var latitude = data["iss_position"]["latitude"];
var longitude = data["iss_position"]["longitude"];
if (!iss) {
iss = L.marker([latitude,longitude]).bindPopup("I am the ISS").addTo(map);
}
iss.setLatLng([latitude,longitude]).update();
setTimeout(update_position, 1000);
});
}
update_position();
DEMO
...by WE.marker. Unfortunately, the updating of the position doesn't work anymore on my 3D globe, whereas it did work on the 2D map.
I tried adding
setInterval(update_position,2000);
just above update_position();, then the marker gets updated a few times (~5) and then suddenly stops. If I interact with my mouse on the globe by panning, the marker gets updated to its current position and gets updated a few times afterwards, and eventually stops again.
Main Question:
Does anyone know how to fix this so that I have a continuous marker update?
Additional Question:
Ideally I would like the International Space Station track to look like https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=CZML.html&label=Showcases, with a colored path the station travelled in its last orbit around the earth. Any tips on how to do this?
Thanks in advance!
[Edit 23-1-2015:
I managed to update it continuously by making a new variable for iis, namely iis2. Why this works is not clear to my. Unfortunately, all 'old' markerpositions don't dissapear, so I get a blurred marker track.
var iss;
var iis2;
function update_position() {
$.getJSON('http://open-notify-api.herokuapp.com/iss-now.json?callback=?', function(data) {
console.log(data);
var latitude = data["iss_position"]["latitude"];
var longitude = data["iss_position"]["longitude"];
if (!iss) {
iss2 = WE.marker([latitude,longitude]).bindPopup("I am the ISS").addTo(map);
}
iss2.setLatLng([latitude,longitude]).update();
});
}
update_position();
setInterval(update_position,1000);
]
remove the marker
var iss;
var iis2;
function update_position() {
$.getJSON('http://open-notify-api.herokuapp.com/iss-now.json?callback=?', function(data) {
console.log(data);
map.removeLayer(iss2);
var latitude = data["iss_position"]["latitude"];
var longitude = data["iss_position"]["longitude"];
if (!iss) {
iss2 = WE.marker([latitude,longitude]).bindPopup("I am the ISS").addTo(map);
}
iss2.setLatLng([latitude,longitude]).update();
});
}
update_position();
setInterval(update_position,1000);
I can have a bunch of locations with different categories to show on the map. Eventually I'd like to apply a filter on them. Probably the scenario is very familiar as I found many of them on the web while I was trying to solve my issue. I put the markers on my map and I can find no way to hide them. Here is how I try it:
function addLocations($content, id, map){
var $mapdiv = $content.find('div.map_div');
catValues = [map.catPrimary, map.catWhite, map.catGreen, map.catYellow, map.catRed, map.catBrown, map.catPurple, map.catGray, map.catOrange];
db.locations.all(function(obj){
$.each(obj, function(index, location){
if(location.value.nodeID == id){
var latitude = location.value.latitude;
var longitude = location.value.longitude;
var description = location.value.description;
var category = location.value.category;
var position = new google.maps.LatLng(latitude, longitude);
if(category == "0"){
homeLocation = position;
$mapdiv.gmap('get','map').setOptions({'center':position});
}
var marker = new google.maps.Marker({
position: position,
icon: "assets/img/marker_" + category + ".png",
category: category,
shadow: iconShadow,
});
marker.setMap( $mapdiv.gmap('get','map') );
$mapdiv.gmap('addMarker', marker).click(function() {
$mapdiv.gmap('openInfoWindow', { 'content': description + "<br/> (" + catValues[category] + ")"}, this);
});
}
});
markers = $mapdiv.gmap('get', 'markers');
for(var i = 0; i<markers.length; i++){
if(markers[i].category != "0"){
//"not primary, hiding
markers[i].setVisibile(false);
}
}
});
All the markers are shown and the ones that are supposed to be hidden are not. I also tried adding the markers to an array before I add them to the map and work with them, but no success. When I include the markers[i].setVisible(false) around a try and catch it says "Object # has no method 'setVisible'. Surprisingly if I test markers[i].getVisible() I get the value true.
I appreciate your help in advance.
I believe the correct code is markers[i].setMap(null);
https://developers.google.com/maps/documentation/javascript/overlays#RemovingOverlays
From the article:
Removing Overlays
To remove an overlay from a map, call the overlay's setMap() method, passing null. Note that calling this method does not delete the overlay; it simply removes the overlay from the map. If instead you wish to delete the overlay, you should remove it from the map, and then set the overlay itself to null.
If you wish to manage a set of overlays, you should create an array to hold the overlays. Using this array, you can then call setMap() on each overlay in the array when you need to remove them. (Note that unlike in V2, no clearOverlays() method exists; you are responsible for keeping track of your overlays and removing them from the map when not needed.) You can delete the overlays by removing them from the map and then setting the array's length to 0, which removes all references to the overlays.