Google Maps v3 move Markers on top when updated - javascript

My App show couriers on Google Maps and as soon as the application receive a GPS update for one of the courier I keep the Map updated with the new courier position. It happen every second for each of my couriers.
The issue is that every time a courier is updated it is moved on top of all others causing a "disco" effect on the map (because couriers may have differe marker color).
I wish to keep the Marker at the same position (in terms of zIndex or whatever) when its position is updated.
How can I do that?
I don't think any code is required here... I do nothing special than create markers and update markers, but I'm pretty sure a comment will arrive with: "show code", so here we are:
funciton createCourierMarkers() {
var couriersStorage = [];
for (var i = 0; i < couriers.length; i++) {
var courier = couriers[i];
var status = courier.status || 'free';
var courierPosition = _getCourierPosition(courier);
var icon = MarkersService.getCourierIcon(status);
var courierMarker = new google.maps.Marker({
map: map,
position: courierPosition,
icon: icon,
zIndex: 200,
type: 'courier',
id: courier.id,
status: status
});
couriersStorage.push(courierMarker);
}
}
function updateCourierMarkerPosition(courier, marker) {
var courierPosition = _getCourierPosition(courier);
marker.setPosition(courierPosition);
}

Related

GMAP creating double marker on same position and not updating marker when values updated?

I am setting number of markers(using png icons) on gmap at the same time but when I update the list the markers should be updated accordingly.
But they didn't gets updated immediately with the list.
First I am clearing the map from markers with this code
for (var i=0; i<this.markerList.length; i++) {
this.markerList[i].setMap(null);
}
// Reset the markers array
this.markerList = [];
Than I am setting the markers again with my initial code which run at the time of mounted
this.markers = this.mappedListings;
this.markerList = this.markers.map((home) => {
var price = home.info.listingPrice
var favList = this.getFavIconOnMap(home);
var url = this.setMarkerIcon(home,favList);
var homeInfo = home.info;
let marker = new this.google.maps.Marker({
position: {
lat: parseFloat(home.position.lat),
lng: parseFloat(home.position.lng),
},
scaledSize: new this.google.maps.Size(18, 18),
icon: url,
label: { color: '#FFFFFF', fontWeight: 'bold', fontSize: '10px', text:String(price)}
});
I am changing the image url by these conditions
var url=''
if(home.info.status === "CT" && favList == false){
url = new google.maps.MarkerImage(
'/assets/icons/contigment.png',
new google.maps.Size(108, 120), //adjust size of image placeholder
new google.maps.Point(-25, -27), //origin
new google.maps.Point(-69,0) //anchor point
);
}
else if(home.info.status === "CT" && favList == true){
url = new google.maps.MarkerImage(
'/assets/icons/contigmentheart.png',
new google.maps.Size(108, 120), //adjust size of image placeholder
new google.maps.Point(-25, -27), //origin
new google.maps.Point(-69,0) //anchor point
);
}
The First Problem is
When I update values in my marker gets updated but there is no change on map until I zoom in or zoom out the map. I Tried every function at the time of updating which I using in my app.
The Second Problem is
When marker updates after zoom in or zoom out of map , then after two three times of update it shows previous marker behind the current marker on map, don't know how it is showing double marker for the same although I empty map every time.
Here is the first picture of marker before updating.
Here is the Second Picture after updated values.
Again when I change List to previous values, according to logic there should be first image but behind this it is showing a part of second image also, as you can see in image below
Not so familiar with gmaps, hope I elaborate the problem clearly.

Leaflet markers aggregating when dezooming the map

I am new to Leaflet and I am trying to show a map with markers.
The problem I have is that the markers disappear when I zoom out, and are replaced with a number:
I used CircleMarkers to be able to set the color of each marker, and so that the markers keep their size no matter the zoom level. I add the markers using markercluster because I want to be able to delete them all easily.
<script src="https://unpkg.com/leaflet.markercluster#1.3.0/dist/leaflet.markercluster.js"></script>
function addMarkers(data){
// setup a marker group
markerList = L.markerClusterGroup();
for (var i = 0; i < data.length; i++){
var circleColor = getcolor(data[i].roundScore);
var circle = L.circleMarker([data[i].solutionLat, data[i].solutionLng], {
color: circleColor,
fillColor: circleColor,
fillOpacity: 0.5,
radius: 5
});
circle.bindPopup("Score : " + data[i].roundScore + "\n Address :" + data[i].address);
markerList.addLayer(circle);
}
window.mapMark.addLayer(markerList);
}
function deleteMarkers(){
if(markerList) {
markerList.clearLayers();
}
}
I have no idea how to change this behavior, and whether it is linked to the markers themselves or to the tile I use, which is openstreetmap:
const attribution =
'© OpenStreetMap contributors';
const tileUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
const tiles = L.tileLayer(tileUrl, { attribution });
tiles.addTo(mapMark);
}
Any help or hint would be greatly appreciated.
Thank you very much :)
The disappearance of your Circle Markers and replacement by numbers is the expected effect of Leaflet.markercluster. should you have included the plugin CSS files as well, these numbers would appear in green/yellow/orange bubbles.
To avoid this clustering, but still be able to remove all your Markers at once, simply use a basic Layer Group instead of a MarkerClusterGroup:
https://leafletjs.com/reference-1.7.1.html#layergroup
Used to group several layers and handle them as one.
markerList = L.layerGroup();
// you can also clear layers of a basic Layer Group
markerList.clearLayers();

Javascript : Load markers on a Google map with a loop

I come for help for a javascript problem.
I'm adding a Google map to my website; this map is currently integrated in my page and works fine.
My problem is that i have a lot of markers to place on the map and i want to use a loop to do it.
The coordinates of the markers are stored in a Site[] table.
For now i have this :
// Create markers on the map
for( i = 0; i < Site.length; i++ )
{
var pos = new google.maps.LatLng(Site[i][7], Site[i][8]); //7 and 8 are the latitude and longitude of the markers.
marker = new google.maps.Marker({
position: pos,
map: maCarte, //my map
title: Site[i][1] //1 is the description of the marker
}
});
And, of course, this doesn't work. Does anybody have an idea ?
You messed up with the different parenthesis... If you would indent your code properly, this would be quite obvious.
// Create markers on the map
for (i = 0; i < Site.length; i++) {
var pos = new google.maps.LatLng(Site[i][7], Site[i][8]); //7 and 8 are the latitude and longitude of the markers.
marker = new google.maps.Marker({
position: pos,
map: maCarte, //my map
title: Site[i][1] //1 is the description of the marker
});
}
If it still doesn't work after you corrected this, then problem must be somewhere else. Without knowing the content of the Site array, we can't help any further.
JSFiddle demo

set Icon on Polygon corners in google map api 3

I have a polygon which is editable so when i start to edit it it shows small icon on it.
Below in picture an arrow icon (for undo changes).
so i want to add another icon by my own so user can delete that polygon by clicking on it. So ho to add icon there?
Update
Here is what i do so far
Link
Now i just want to add icon when polygon complete event fired.
So you've already got the event listener for when the polygon is complete.
What you could do is add a marker in the middle of your polygon, with a custom icon that looks similar or identical to the 'undo' icon Google are using.
google.maps.event.addListener(drawingManager, 'polygoncomplete', function(polygon) {
drawingManager.setDrawingMode(google.maps.drawing.OverlayType.FALSE);
// find out the paths of this polygon
var path = polygon.getPath();
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < path.length; i++) {
bounds.extend(path.getAt(i));
}
var centre = bounds.getCenter();
// add a marker here:
var marker = new google.maps.Marker({
position: centre,
map: map,
icon: 'https://google-developers.appspot.com/maps/documentation/javascript/examples/full/images/beachflag.png'
});
});

Preventing Google Maps Move After Displaying Infowindow

I'm trying to display a infowindow on a Google Maps. It displays perfect, when you hover over a marker it loads up a infowindow but the map jumps to fit in the window. I don't want the map to move but rather infowindow set its position according to map. Booking.com has something like this.
EDIT: Added my code
Here is the stripped down version of my code. I'm getting all the info from an AJAX service and this service returns response (which holds some more info too).
$.ajax({
url: 'URL',
dataType: "json",
type: "GET",
success: function(response) {
// delete all markers
clearOverlays();
var infowindow = new google.maps.InfoWindow();
for (var i = 0; i < response.length; i++) {
item = response[i];
var marker = new google.maps.Marker({
position: new google.maps.LatLng(item.lat, item.lng),
map: map,
url: item.detail_url
});
markersArray.push(marker);
// display infowindow
google.maps.event.addListener(marker, "mouseover", (function(marker, item) {
return function() {
infowindow.setOptions({
content: 'SOME CONTENT HERE FOR INFOWINDOW'
});
infowindow.open(map, marker);
}
})(marker, item));
// remove infowindow
google.maps.event.addListener(marker, 'mouseout', function() {
infowindow.close();
});
// marker click
google.maps.event.addListener(marker, 'click', function() {
window.location.href = marker.url;
});
}
}
});
As you can see below, the first image shows the infowindow displayed at bottom of marker while second one shows the infowindow displayed on top of the marker. The map doesn't move but infowindow sets its position within the boundries of the map.
In your declaration for setting the info window options infowindow.setOptions, add the following option to disable the panning of the map when the infowindow is displayed, disableAutoPan : true.
However this will also mean you'll need to calculate the real estate you have available to display the infowindow on your map and give it a position using the position option. Otherwise it won't be guaranteed that your infowindow will be completely visible on the map.
https://developers.google.com/maps/documentation/javascript/reference#InfoWindowOptions
EDIT: How to calculate screen real estate
I realize I was pretty vague with my suggestion to calculate the screen real estate available to set the position of your infowindow, when part of your question was to actually set the infowindow's position. So I've provided an update to my answer on how you can calculate the screen real estate and adjust your infowindow's position.
The key is to first convert your points from LatLng to pixels, and find out the pixel coordinate of the marker on the map with relation to the pixel coordinate of the map's center. The following snippet demonstrates how this can be done.
getPixelFromLatLng: function (latLng) {
var projection = this.map.getProjection();
//refer to the google.maps.Projection object in the Maps API reference
var point = projection.fromLatLngToPoint(latLng);
return point;
}
Once you've got your pixel coordinates, you'll need to find out which quadrant of the map canvas the marker is currently residing in. This is achieved by comparing the X and Y coordinates of the marker to the map, like so:
quadrant += (point.y > center.y) ? "b" : "t";
quadrant += (point.x < center.x) ? "l" : "r";
Here, I'm determining if the point is in the bottom right, bottom left, top right or top left quadrant of the map based on it's relative position to the map's center. Keep in mind this is why we use pixels as opposed to LatLng values, because LatLng values will always yield the same result - but reality is the marker can be in any quadrant of the map canvas depending on panning.
Once you know which quadrant the marker is in, you can give offset values to the infowindow to position it so it's visible on the map - like so:
if (quadrant == "tr") {
offset = new google.maps.Size(-70, 185);
} else if (quadrant == "tl") {
offset = new google.maps.Size(70, 185);
} else if (quadrant == "br") {
offset = new google.maps.Size(-70, 20);
} else if (quadrant == "bl") {
offset = new google.maps.Size(70, 20);
}
//these values are subject to change based on map canvas size, infowindow size
Once the offset value is determined you can just adjust the pixelOffset of your infowindow on whatever listener you have invoking the infoWindow.open() method. This is done by using the setOptions() method for infowindows:
infowindow.setOptions({pixelOffset : self.getInfowindowOffset(self.map, marker)});
Here is a working JSFiddle example of the solution described above.
Note: You will notice the annoying "arrow" on the infowindow displaying desbite the position of your infowindow, this is part of the default Google Map's setting for infowindows and I could not find a proper way of getting rid of it. There was a suggestion here, but I couldn't get it to work. Alternatively you can use the infobox library or the infobubble library - which gives you more styling options.
Suvi Vignarajah's answer is great, what I didn't like about it was how unpredictable the position of the window is near the edges.
I tweaked it so that the bubble glues to the wall as it should be expected: http://jsfiddle.net/z5NaG/5/
The only condition is that you need to know the width & height of the infoWindow, you can position it quite nicely. You would work it out through the maps' pixels. If you don't know it you could initialize the InfoWindow offscreen, get it's size and proceed opening it again at the right spot. Ugly but would work.
First initialize on overlay at time of map initialization by running this function:
ourOverlay:null,
createOverlay:function(){
this.ourOverlay = new google.maps.OverlayView();
this.ourOverlay.draw = function() {};
this.ourOverlay.setMap(this.map);
},
Then at open event adjust the offset like so:
getInfowindowOffset: function (map, marker) {
// Settings
var iwWidth = 240; // InfoWindow width
var iwHeight = 190; // InfoWindow Height
var xOffset = 0;
var yOffset = 0;
// Our point of interest
var location = this.ourOverlay.getProjection().fromLatLngToContainerPixel(marker.getPosition());
// Get Edges of map in pixels: Sout West corner and North East corner
var swp = this.ourOverlay.getProjection().fromLatLngToContainerPixel(map.getBounds().getSouthWest());
var nep = this.ourOverlay.getProjection().fromLatLngToContainerPixel(map.getBounds().getNorthEast());
// Horizontal Adjustment
if(location.x<iwWidth/2){
xOffset= iwWidth/2-location.x;
}else if(location.x>nep.x-iwWidth/2){
xOffset = (nep.x-iwWidth/2)-location.x ;
}
// Vertical Adjustment
if(location.y<iwHeight){
yOffset = location.y + iwHeight-(location.y-nep.y);
}
// Return it
return new google.maps.Size(xOffset, yOffset);
},
And the result is pretty nice, but this triangle seems out of place now.
You can use InfoBox to remove the pointy arrow on bottom:
GmapsManager.infowindow = new InfoBox({
content:'',
alignBottom: true,
closeBoxURL: "",
});
and style the bubble with the following code:
.infobox-popup{
background: #fff;
-webkit-border-radius: 3px;
border-radius: 3px;
padding: 5px;
margin-left: -100px;
margin-bottom: 30px;
width: 200px;
-webkit-box-shadow: 0 0 1px 0 #595959;
box-shadow: 0 0 1px 0 #595959;
}

Categories