Update marker position on google map without page load - javascript

I'm trying to update the google map marker position in every 20 seconds which comes from database but it's doesn't work.
Code :
for (i = 0; i < purple.length; i++) {
if (purple[i][1] == latitude && purple[i][2] == longitude) {
nogreen = 1;
}
marker = new google.maps.Marker({
position : new google.maps.LatLng(purple[i][1], purple[i][2]),
map : map,
title : purple[i][0],
data : purple[i][0],
zoom : maxZoomService,
icon : 'img/purple.png',
shadow : 'img/purple.png'
});
setInterval(function () {
position : new google.maps.LatLng(purple[i][1], purple[i][2]),
marker.setPosition(position);
}, 20000);
};
Is this correct or how can i do that ?

This code here isn't valid javascript:
setInterval(function() {
position: new google.maps.LatLng(purple[i][1], purple[i][2]),
marker.setPosition(position);
}, 20000);
You want to do:
setInterval(function() {
position = new google.maps.LatLng(purple[i][1], purple[i][2]);
marker.setPosition(position);
}, 20000);

Related

Leaflet - set icon based on zoom WITH a timeout refresh

I'd like to have my icon change based on the zoom, which I have working! BUT, I also have a setTimeout which runs my function every 7 seconds.
The problem is that every time the function is run, the icon gets set back to the bigBusIcon.
I've tried putting both the marker and the zoomend in functions, but I've had no luck... Any help is much appreciated!
const mapBuses = function () {
//other code is here
L.geoJSON(getGeoJson(routeFilter), {
onEachFeature: function (feature) {
let longitude = feature.coordinates[0];
let latitude = feature.coordinates[1];
let marker = L.marker([latitude, longitude], { icon: bigBusIcon, rotationAngle: feature.bearing })
.bindPopup(
`Bus Route: ${feature.routeNum}<br/>Speed: ${Math.round(feature.speed)} km/hr`
).addTo(busLayer);
// set icon size based on zoom (although it resets every 7 seconds)
map.on('zoomend', function () {
var currentZoom = map.getZoom();
if (currentZoom >= 14) {
marker.setIcon(bigBusIcon);
}
else {
marker.setIcon(smallBusIcon);
}
});
}
});
});
// refresh every 7 seconds
setTimeout(mapBuses, 7000);
};
You can check the current zoom while you are initializing your layer:
const mapBuses = function () {
//other code is here
L.geoJSON(getGeoJson(routeFilter), {
onEachFeature: function (feature) {
let longitude = feature.coordinates[0];
let latitude = feature.coordinates[1];
// get current zoom
let currentZoom = map.getZoom();
// add condition to chose icon
let myIcon = currentZoom > 14 ? bigBusIcon : smallBusIcon;
// use myIcon variable in marker creation
let marker = L.marker([latitude, longitude], { icon: myIcon, rotationAngle: feature.bearing })
.bindPopup(
`Bus Route: ${feature.routeNum}<br/>Speed: ${Math.round(feature.speed)} km/hr`
).addTo(busLayer);
// set icon size based on zoom (although it resets every 7 seconds)
map.on('zoomend', function () {
var currentZoom = map.getZoom();
if (currentZoom >= 14) {
marker.setIcon(bigBusIcon);
}
else {
marker.setIcon(smallBusIcon);
}
});
}
});
});
// refresh every 7 seconds
setTimeout(mapBuses, 7000);
};

How to stop set Interval flickering using angular 2+

Here i am displaying the dynamic data i.e lat and long on the google maps and here i am applying the setInterval() below is my code:
this.timer = setInterval(()=>{this.getMapData();},30000);
here the issue is when ever the data is updating or calling the this.getMapData() then the map is also flickering.Is It possible to update the data for every 30 sec with out flickering the div/map
getMapData() {
this.spinner.show();
this.serv.getMapData(this.ds, this.ln).subscribe(res => {
this.spinner.hide();
this.deleteMarkers();
if (res.Data && res.Data.length > 0) {
this.mapData = res.Data;
console.log(JSON.stringify(this.mapData));
if (this.mapData != null && this.mapData.length > 0) {
for (var i = 0; i < this.mapData.length; i++) {
var latlng = {lat: parseFloat(this.mapData[i].latitude), lng: parseFloat(this.mapData[i].longitude)};
this.addMarker(latlng, this.mapObject, this.mapData[i].Name);
this.markerName = this.mapData[i].Name;
}
}
} else {
this.toastr.error('No Data Found', 'Oops!');
}
},err=>{
this.spinner.hide();
});
}
addMarker(latlng, mapobj, markerLabel) {
var marker = new google.maps.Marker({
position: latlng,
label: '',
map: mapobj,
animation: google.maps.Animation.DROP,
});
var infowindow = new google.maps.InfoWindow({
content: markerLabel
});
google.maps.event.addListener(marker, 'click', function() {
// infowindow.open(Map,marker);
});
infowindow.open(Map,marker);
// This is for set postion for the marker after getting dynamic data it posittions to the point
mapobj.setZoom(17);
mapobj.panTo(marker.position);
this.markers.push(marker);
}
// Sets the map on all markers in the array.
setMapOnAll(map) {
for (var i = 0; i < this.markers.length; i++) {
this.markers[i].setMap(map);
}
}
// Removes the markers from the map, but keeps them in the array.
clearMarkers() {
this.setMapOnAll(null);
}
// Deletes all markers in the array by removing references to them.
deleteMarkers() {
this.clearMarkers();
this.markers = [];
}
Based on our discussion :
inside the addMarker() ,
if(this.marker != null){
this.marker = new google.maps.Marker({
position: latlng,
label: '',
map: mapobj,
animation: google.maps.Animation.DROP,
});
}
else{
this.marker.setPosition(latlng);
}
So at first it will check if marker is null .If it is null then a new marker object is created . If not , then the marker's position is changed to the dynamic latlng.
So your , map flickering issue will be resolved as only the marker position is changing . Also remove the this.deleteMarkers() as you are changing position now , there is no need of deleting the marker from map.
Now , instead of using a setInterval , you can use rxjs operator interval to call the service and fetch data once in 30 seconds or whatever your time is .
To do this , inside your service do something like this :
return Observable.interval(30000).flatMap(()=>{
return this.http.get(url + data+'/LocationId='+ param).map(res => {
return res.json();
});
)};
EDIT
You'll need the following imports :
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/mergeMap`;

Open Layer 3 Animation

i want to animate a marker in Ol3. I used this example from Ol.
The Animation works but with a little bug an i dont know how to fix it.
//main animating loop
var moveFeature = function(event) {
var vectorContext = event.vectorContext;
var frameState = event.frameState;
if (animating) {
var elapsedTime = frameState.time - now;
var now1 = new Date().getTime();
if((now1 - lastTime) > 100){
// stop if end reached
if(curIndex >= coordinates.length){
stopAnimation(true);
requestData(true);
// console.log(" end ");
return;
}
var newPoint = coordinates[curIndex];
var lastP = newPoint;
if(curIndex>=1)
lastP = coordinates[curIndex-1];
if(newPoint !== null & typeof newPoint != " undefined "){
curPoint = ol.proj.fromLonLat(newPoint);
lastCourse = course;
// calculate azimuth between two coordinates
course = calcBearing(lastP,newPoint);
lastTime = now1;
}
curIndex++;
lastTime = now1;
}
//every time render marker position ?? needed ? or only when new one
geoMarker.getGeometry().setCoordinates(curPoint);
//styles.geoMarker.getImage().setRotation(course); //rotates the feature
debugger;
lastCourse = course;
vectorContext.drawFeature(geoMarker, styles.geoMarker);
// do we need follow the bus due to rendering out of current extend =
calcExtend();
}
// tell OL3 to continue the postcompose animation
map.render();
};
I draw the new pos of the marger with vectorContext.drawFeature(geoMarker, styles.geoMarker);
Every time the new position is plotted the vectorlayer is new generated. I dont know why.
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [geoMarker]
//features: [pointFeature]
}),
style: function(feature) {
// hide geoMarker if animation is active
if (animating && feature.get('type') === 'geoMarker') {
// TODOBug
return styles[feature.get('type')];
}
return styles[feature.get('type')];
}
});
With this example above i get the following problem on the map. If the map is clicked, the marker duplicates, one marker stays at the old position and the other one is moving forwoard. Thats a problem.
When i change the code of the vectorlayer like this.
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [geoMarker]
//features: [pointFeature]
}),
style: function(feature) {
// hide geoMarker if animation is active
if (animating && feature.get('type') === 'geoMarker') {
debugger;
console.log("return null")
// TODOBug
return null;
}
return styles[feature.get('type')];
}
});
The problem with the duplicate marker is solved but then the marker isnt clickable while the animation is in progess.
The Question is: How can i achieve that the marker doesen´t duplicates and is clickable while animating???

Remove markers out of viewport

I have to manage a map of about 80.000 markers concentrated in France.
To do that, I decided to get the bounds of the viewport and call a dynamic-JSON (with PHP) which contains the markers inside the viewport. And this on the "idle" event.
I faced a problem with this solution. Indeed, the markers which already exist was re-plotted (at the same position), which consequently weigh the map for nothing...
To solve it, the markers list before and after the JSON query are compared (thanks to jQuery), in order to plot only the new markers. And it works!
Now, I would want to remove the markers which are not currently shown on the map. Or a list of markers (I get it thanks to jQuery) designated by an ID which is also the title of the marker. So, how can a delete markers like that ? I specify that I am using MarkerManager.
Otherwise, you guess that if I do not remove these markers, they will be re-plotted in some cases... For example, you are viewing the city A, you move the map to view the city B, and you get back to the city A...
Here is the code:
var map;
var mgr;
var markers = [];
function initialize(){
var mapOptions = {
zoom: 6,
center: new google.maps.LatLng(46.679594, 2.109375)
};
map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var mgrOptions = { borderPadding: 50, maxZoom: 15, trackMarkers: false };
mgr = new MarkerManager(map, mgrOptions);
google.maps.event.addListener(map, 'idle', function() {
mapEvent();
});
}
function mapEvent(){
if( map.getZoom() >= 8 ){
var bounds = map.getBounds();
getSupports(bounds.getNorthEast(), bounds.getSouthWest());
} else {
// Todo
}
}
var markerslistID = new Array();
var markerslistData = {};
function getSupports(ne, sw){
newMarkerslistID = new Array();
newMarkerslistData = {};
// Getting the markers of the current view
$.getJSON('./markerslist.php?nelat='+ne.lat()+'&nelng='+ne.lng()+'&swlat='+sw.lat()+'&swlng='+sw.lng(), function(data) {
for (var i = 0; i < data.points.length; i++) {
var val = data.points[i];
newMarkerslistID.push(val.id);
newMarkerslistData[val.id] = new Array(val.lat, val.lng, val.icon);
}
// List of New Markers TO PLOT
var diffNewMarkers = $(newMarkerslistID).not(markerslistID).get();
// List of Old markers TO REMOVE
var diffOldMarkers = $(markerslistID).not(newMarkerslistID).get();
// Plotting the NEW MARKERS
for( var i = 0; i < diffNewMarkers.length; i++ ){
var marker = new google.maps.Marker({
position: new google.maps.LatLng(newMarkerslistData[diffNewMarkers[i]][0], newMarkerslistData[diffNewMarkers[i]][1]),
title : diffNewMarkers[i],
icon : './images/'+newMarkerslistData[diffNewMarkers[i]][2]+'.png'
});
mgr.addMarker(marker, 0);
}
/*****************************************
HERE WE HAVE TO REMOVE
THE MARKERS CONTAINED IN diffOldMarkers
*****************************************/
mgr.refresh();
// Switching the new list to the old, for the next event
markerslistID = newMarkerslistID;
markerslistData = newMarkerslistData;
});
}
Thank you for your help.
A one-liner to hide all markers that ar not in the current viewport.
!map.getBounds().contains(marker.getPosition()) && marker.setVisible(false);
Or,
if (map.getBounds().contains(marker.getPosition()) && !marker.getVisible()) {
marker.setVisible(true);
}
else if (!map.getBounds().contains(marker.getPosition()) && marker.getVisible()) {
marker.setVisible(false);
}

Show a moving marker on the map

I am trying to make a marker move(not disappear and appear again) on the map as a vehicle moves on the road.
I have two values of latLng and I want to move the marker between the two till the next point is sent by the vehicle. And then repeat the process again.
What I tried:[This is not a very efficient way, I know]
My thought was to implement the above using the technique in points below:
1) Draw a line between the two.
2) Get the latLng of each point on 1/10th fraction of the polyline.
3) Mark the 10 points on the map along with the polyline.
Here is my Code:
var isOpen = false;
var deviceID;
var accountID;
var displayNameOfVehicle;
var maps = {};
var lt_markers = {};
var lt_polyLine = {};
function drawMap(jsonData, mapObj, device, deleteMarker) {
var oldposition = null;
var oldimage = null;
var arrayOflatLng = [];
var lat = jsonData[0].latitude;
var lng = jsonData[0].longitude;
//alert(jsonData[0].imagePath);
var myLatLng = new google.maps.LatLng(lat, lng);
if (deleteMarker == true) {
if (lt_markers["marker" + device] != null) {
oldimage = lt_markers["marker" + device].getIcon().url;
oldposition = lt_markers["marker" + device].getPosition();
lt_markers["marker" + device].setMap(null);
lt_markers["marker" + device] = null;
}
else {
console.log('marker is null');
oldimage = new google.maps.MarkerImage(jsonData[0].imagePath,
null,
null,
new google.maps.Point(5, 17), //(15,27),
new google.maps.Size(30, 30));
oldposition = myLatLng;
}
}
var image = new google.maps.MarkerImage(jsonData[0].imagePath,
null,
null,
new google.maps.Point(5, 17), //(15,27),
new google.maps.Size(30, 30));
lt_markers["marker" + device] = new google.maps.Marker({
position: myLatLng,
icon: image,
title: jsonData[0].address
});
if (oldposition == myLatLng) {
alert('it is same');
lt_markers["marker" + device].setMap(mapObj);
mapObj.panTo(myLatLng);
}
else {
alert('it is not same');
var markMarker = null;
var i = 10;
for (i = 10; i <= 100; i + 10) {
//-------
// setTimeout(function() {
if (markMarker != null) {
markMarker.setMap(null);
markMarker = null;
}
alert('inside the loop');
var intermediatelatlng = mercatorInterpolate(mapObj, oldposition, myLatLng, i / 100);
alert('Intermediate Latlng is :' + intermediatelatlng);
arrayOflatLng.push(intermediatelatlng);
var flightPath = new google.maps.Polyline({
path: arrayOflatLng,
strokeColor: "#FFFFFF",
strokeOpacity: 1.0,
strokeWeight: 1
});
flightPath.setMap(mapObj);
if (i != 100) {
markMarker = new google.maps.Marker({
position: intermediatelatlng,
icon: image,
title: jsonData[0].address,
map: mapObj
});
}
else {
markMarker = new google.maps.Marker({
position: intermediatelatlng,
icon: oldimage,
title: jsonData[0].address,
map: mapObj
});
}
mapObj.panTo(intermediatelatlng);
//--------
// }, 1000);
}
}
}
function mercatorInterpolate(map, latLngFrom, latLngTo, fraction) {
// Get projected points
var projection = map.getProjection();
var pointFrom = projection.fromLatLngToPoint(latLngFrom);
var pointTo = projection.fromLatLngToPoint(latLngTo);
// Adjust for lines that cross the 180 meridian
if (Math.abs(pointTo.x - pointFrom.x) > 128) {
if (pointTo.x > pointFrom.x)
pointTo.x -= 256;
else
pointTo.x += 256;
}
// Calculate point between
var x = pointFrom.x + (pointTo.x - pointFrom.x) * fraction;
var y = pointFrom.y + (pointTo.y - pointFrom.y) * fraction;
var pointBetween = new google.maps.Point(x, y);
// Project back to lat/lng
var latLngBetween = projection.fromPointToLatLng(pointBetween);
return latLngBetween;
}
Problems Faced:
1) The marker is not showing up on the map because the process of plotting and removal of marker is so fast that the marker is not visisble on screen. I've tried setTimeOut, and It does not help at all.
2) if I alow the browser to run this code for more than 5 minutes, the browser crashes.
Note: The Above function is called every 10 seconds using setInterval.
What Can be a better solution? Please Help..
For the marker to move relatively smoothly, you need to
Update more than every 1/10 fraction of the polyline (at least every few pixels)
Call the update method more frequently
Don't delete and re-add the marker
For example, something like:
var counter = 0;
interval = window.setInterval(function() {
counter++;
// just pretend you were doing a real calculation of
// new position along the complex path
var pos = new google.maps.LatLng(35, -110 + counter / 100);
marker.setPosition(pos);
if (counter >= 1000) {
window.clearInterval(interval);
}
}, 10);
I made a simple example at http://jsfiddle.net/bmSbU/2/ which shows a marker moving along a straight path. If this is what you want, most of your code above regarding where along the line you are can be reused (or check out http://broady.github.io/maps-examples/points-along-line/along-directions.html )
You can use marker-animate-unobtrusive library to make markers
smoothly transition from one location to another (instead of reappearing).
You could initialize your marker like that:
var marker = new SlidingMarker({
//your original marker options
});
Just call marker.setPosition() each time new vehicle's coordinate arrive.
P.S. I'm the author of the library.
Why not keep the existing Marker/ MarkerImage and call setPosition() to move it, either on a timer or as the position changes?
Deleting it & recreating it is what causes it to flash/ flicker and eventually crash. If you keep the same instance but just move it, you should do much better.
See: Marker.setPosition()
https://developers.google.com/maps/documentation/javascript/reference#Marker

Categories

Resources