Trailing route polyline on marker move event - javascript

I am using leaflet and pubnub libraries to move marker smoothly on Google maps, with real-time data. This functionality is working fine and marker moves smoothly on map from one point to next point.
But I could not find a way to draw a route polyline from marker to destination and trailing line with marker move event. I want to show route line same as Uber, from car icon to destination and trailing line with car movement.
Any help would be appreciated.
I am using the following pubnub SDK:
https://www.pubnub.com/developers/eon/map/bus/
Here is my pubnub object initialization code:
var connectline = 0;
var lastlng = [40.80523269999999, -73.7412536];
var pubnub = new PubNub({
publishKey: 'pub-c-5e4c8233-c59b-448c-a809-9c09f61715XX',
subscribeKey: 'sub-c-74a7e51a-ad14-11e4-a808-02ee2ddab7XX'
});
var trip = '134386886'; // '134386875';
var channel = 'TRIP_' + trip;
alert("channel name=" + channel);
var map = eon.map({
pubnub: pubnub,
id: 'map',
options: {
center: new L.LatLng(40.80523269999999, -73.7412536),
zoom: 15
},
mbId: 'ianjennings.l896mh2e',
mbToken: 'pk.eyJ1IjoiaWFuamVubmluZ3MiLCJhIjoiZExwb0p5WSJ9.XLi48h-NOyJOCJuu1-h-Jg',
channels:[channel],
message: function (data) {
map.setView(data[trip].latlng, 15);
},
transform: function(m) {
var a = {};
a[m.common.trip_id] = {
latlng: [m.common.latitude, m.common.longitude],
data: m.common
}
return a;
},
rotate: true,
// history: true,
marker: function (latlng, data) {
var icon = new Icon();
var parisKievLL = [lastlng, latlng];
var marker = L.Marker.movingMarker(parisKievLL, [10000], {icon:icon}).addTo(map);
lastlng = latlng;
// alert('marker data=' + JSON.stringify(data));
// alert('market latlng' + JSON.stringify(latlng));
// var latlng = [data.latitude, data.longitude];
var addressMarker = L.marker([40.80523269999999, -73.7412536]).addTo(map);
marker.bindPopup('car #:' + data.device_id);
return marker;
}
});

Related

How to centre the google map after fitbound

I need some help with Google maps.
I am not able to reduce the zoom level in google maps after fitbound.
The problem is that I am getting a very highly zoomed google map. I have tried setting the zoom level to 5 (as you can see in the codes) but this has no effect to the very highly zoomed map.
I want to achieve this
But right now its coming like this : http://redstoneinfotech.com/OSAcontact/
Here is the map.js
window.map = {
map_type: 'ROADMAP',
map_zoom: 5,
map_style: 'blackwhite',
map_scrollable: 'on',
marker: 'show',
label: ['Castle Hill', 'Sydney', 'Melbourne', 'Milton', 'Brooklyn Park', 'Wangara '],
address: '',
latlng: ['-33.7301484, 150.9626532', '-33.8473567, 150.6517813',
'-37.970154, 144.4926753 ', ' - 27.4691402, 152.9962768 ',
' - 34.9303517, 138.5346949 ', ' - 31.7928896, 115.8157212 '
],
center_latlng: '',
markerURL: 'assets/images/marker.png',
auto_center: true,
};
'use strict';
jQuery(document).ready(function($) {
$('.google-map').each(function() {
var mapDiv = $(this);
var mapData = window[mapDiv.attr('id')];
function createMap() {
var style = [{
'stylers': [{
'saturation': -100
}]
}];
var options = {
zoom: parseInt(mapData.map_zoom, 5),
scrollwheel: false,
draggable: mapData.map_scrollable === 'on',
mapTypeId: google.maps.MapTypeId[mapData.map_type]
};
if (mapData.map_style === 'blackwhite') {
options.styles = style;
}
return new google.maps.Map(mapDiv[0], options);
}
// create map
var map = createMap();
// create bounds in case we dont have center map coordinates
// every time a marker is added we increase the bounds
var bounds = new google.maps.LatLngBounds();
function addMarker(position, index) {
if (mapData.marker === 'show') {
var image = {
url: mapData.markerURL,
size: new google.maps.Size(30, 48),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(10, 40)
};
var marker = new google.maps.Marker({
position: position,
icon: image,
map: map
});
// extend bounds to encase new marker
bounds.extend(position);
// add label popup to marker
if (mapData.label[index] !== undefined) {
var infoWindow = new google.maps.InfoWindow({
content: mapData.label[index]
});
google.maps.event.addListener(marker, 'click', function(e) {
infoWindow.open(map, this);
});
}
}
}
// centre map
var centerMapWithCoordinates = !mapData.auto_center;
if (centerMapWithCoordinates) {
if (mapData.center_latlng !== undefined) {
var center_lat_lng = mapData.center_latlng.split(',');
var center_map = new google.maps.LatLng(center_lat_lng[0], center_lat_lng[1]);
map.setCenter(center_map);
} else {
console.log('You have not set any coordinates for the map to be centered at.');
}
}
// create markers
if (mapData.address) {
// lookup addresses
var markerAddressCount = 0;
$.each(mapData.address, function(index, address) {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': address
}, function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
if (undefined !== results[0]) {
var location = results[0].geometry.location;
var position = new google.maps.LatLng(location.lat(), location.lng());
addMarker(position, index);
}
// increment count so we can keep track of all markers loaded
markerAddressCount++;
// if all markers are loaded then fit map
if (!centerMapWithCoordinates && markerAddressCount === mapData.address.length) {
map.fitBounds(bounds);
}
} else {
console.log('Geocode was not successful for the following reason: ' + status);
}
});
});
} else if (undefined !== mapData.latlng) {
for (var i = 0; i < mapData.latlng.length; i++) {
var coordinates = mapData.latlng[i].split(',');
var position = new google.maps.LatLng(coordinates[0], coordinates[1]);
addMarker(position, i);
}
if (!centerMapWithCoordinates) {
map.fitBounds(bounds);
}
}
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
this.setZoom(5);
google.maps.event.removeListener(boundsListener);
});
});
});
I have tried with many options but none of them is working. Please help.
As much as I can see, the problem is with the Google Maps sdk. Why? because they are calling to bounds_changed callback before the fitBounds is actually ended.
That's why it causes the zoom not to work because they didn't finish to zoom it as part as the bounds changing in fitBounds.
So the solution is to put the setZoom in setTimeout. In this way, this code will run only after the execution of the current process - fitBounds.
setTimeout(() => {
this.setZoom(5);
}, 0);
It works for me. Let me know if it works for you.

Duplicate click event listeners for different markers : google maps

Introduction
I am working with google maps, displaying markers having different infoWindow. I am making an ajax call to update the map markers with related info windows. After successful ajax call, map render function called and map updated 'rightly'.
Problem
After ajax call, map updated but the problem is that each marker has the same duplicate infowindow. In other words, infowindow is not binding with markers respectively.
Javascript Code
I am sure problem is on clickEventListener. Comments are for info.
//map rendering start
function renderMap(dd) {
console.log('after ', dd);
for (var a = 0; a < dd; a++) {
console.log('after ', dd);
}
var dataArr = [];
var mapProp = {
center: abc,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("googleMap"), mapProp);
for (var a = 0; a < dd.length; a++) {
dataArr.push({ location: new google.maps.LatLng(dd.location.coordinates[1], dd.location.coordinates[0]), weight: 2 });
var contentString = dd;
var infowindow = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: { lat: dd.location.coordinates[1], lng: dd.location.coordinates[0] },
label: "B",
map: map
});
console.log("before event listener", contentString);//Correctly displayed
google.maps.event.addListener(marker, 'click', function () {
//when click on marker, console is logged
console.log("after event listener", contentString);//Wrongly log same contentString
infowindow.open(map.get('map'), marker);
});
// Add circle overlay and bind to marker
var circle = new google.maps.Circle({
map: map,
radius: 5000, // 10 miles in metres
fillColor: '#4682b4'
});
circle.bindTo('center', marker, 'position');
//console.log(e.location] + ',' + e.location.coordinates[0]);
//start of inner for
}
var heatmap = new google.maps.visualization.HeatmapLayer({
data: dataArr
});
}
//map rendering end
function ajaxHeatMapHandler() {
var dataEl = $('#heatmapFilterArea');
var data = {};
//make ajax resquest
$.ajax({
type: "POST",
url: "/",
data: data,
success: function (response, status) {
heatmapTitle.text(responselength + ' entries');
renderMap(response);
},
});
}
I am trying to figure out what has gone wrong and now turned to SO, if anyone have idea or knowledge for this problem, please do help. Thanks for your time.
Check the great answer by Leigh here
The problem is the way how you create info window, not the event handler I think.

Google Maps filtering by multiple regions (polygons)?

I am working with a map in which I am interested in having multiple regions selected and when those regions have been selected they only pins that show are those regions. Essentially, the site currently has the "tags" set up so when you click on a region, the corresponding tag displays under the filter. After the filter is added each marker is compared and if that marker is not in a region the tag is removed. Currently, the map was functioning when selecting a drop down item and comparing this item with the polygon region for each marker. However, the moment you add another loop for each tag the filtering no longer works. Below is my code and the website link is at http://swishercorbett.com.test.marketmagnitude.com/listings/?map=1
var DistrictVal = jQuery('#District').val();
var baths = jQuery('#baths').val();
var bedrooms = jQuery('#bedrooms').val();
//var amount = jQuery('listings_per_page')
var minprice = jQuery('#minPriceB').val();
var maxprice = jQuery('#maxPriceB').val();
jQuery('#loading').show(); //show the loading icon on start before a selection is made
/* ===================================================================================================================*/
var stopIt = [];
var bad;
var DistrictLen = jQuery('#District option').length; // determine how many items there are
for(var i = 0; i <= DistrictLen; i++) //loop through each item in the drop down
{
var optionText = jQuery('#District option').eq(i).text(); //get the text and put in variable
}
//loop through each filter tag added
// if the filter tag matches drop down selection
// make sure not to add the new tag
var districtTags = jQuery('#districtTags #districtTag')
var tagLength = districtTags.length;
for (var z = 0; z <= tagLength; z++)
{
if (districtTags.eq(z).text() == DistrictVal)
{
stopIt.push(1); //there is a match
}
else{
stopIt.push(0); // there is not a match
}
}
var bad = jQuery.inArray(1, stopIt);
if (bad == -1)
{
jQuery('#districtTags').append('<div id="tag"><div id="districtTag">'+DistrictVal+'</div><span id="remove-tag"> X</span></div>');
tags.push(DistrictVal); //get all of the tags and send them to mapChange() which is in jGMap.js
//console.log(tags);
}
jQuery('#remove-tag').live('click',function()
{
jQuery(this).parent().empty();
tags = [];
});
/* ===================================================================================================================*/
//New Ajax request indepentant from the below Ajax request which
// is only used to retrieve listings by location
infoWindow = new google.maps.InfoWindow({size: new google.maps.Size(150, 100)});
var mapOptions = {
center: new google.maps.LatLng(39.977735,-86.141566),
zoom: 11,
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map-canvas-listing"), mapOptions);
geoXml = new geoXML3.parser({map: map, singleInfoWindow: true, infowindow: infoWindow});
geoXml.parse('/wp-content/themes/swishercorbett/js/SC Map.kml');
/* ================================================================================ */
//Adds inforation to the database with the address and the latitude and longitude
jQuery.ajax({
async: 'false',
url: 'http://swishercorbett.com.test.marketmagnitude.com/wp-content/plugins/john- real-estate/mapinformation.php', //not a real page
type: 'GET',
dataType: 'json',
data: {jbaths: baths, jbedrooms: bedrooms, jminprice: minprice, jmaxprice: maxprice},
//data: {jaddr: addr, jlat: lat, jlon: lon}, //uncomment after use!
success: function(e)
{ // get each address
jQuery(e).each(function(index)
{
// e[0] is first item repeated over itself
var text = e[index][0]; //get the address of each listing
//console.log(text);
var cords = e[index][1].split(','); //get the latitude and longitude and spit
var lat = parseFloat(cords[0]); //latitude with decimal points
var lon = parseFloat(cords[1]); // longitude with decimal points
infowindow = new google.maps.InfoWindow();
marker = new google.maps.Marker( //add a new marker for each item in JSON array
{
position: new google.maps.LatLng(lat, lon), // create a new position
map: map // add the position to the map
});
/* ============================================================================ */
for(var i = 0; i<geoXml.docs[0].gpolygons.length; i++ )
{
// if any of the tags match show those districts, remove the rest
for( var z = 0; z<= tags.length; z++)
{
if( geoXml.docs[0].placemarks[i].name == tags[z] ) //DistricVal
{
if (geoXml.docs[0].gpolygons[i].Contains(marker.getPosition()) )
{ //if the marker is in the first quadriant then keep it, else remove the marker from the map
marker.setMap(map);
setTimeout(function(){ jQuery('#loading').hide(); }, 500);
}
else
{
marker.setVisible(false);
//console.log('does not contain');
}
}
else
{
//alert('there is not a kml region with that name')
}
}
}
/* ============================================================================ */
//console.log(google.maps.geometry.poly.containsLocation(cords, Midtown));
google.maps.event.addListener(marker, 'click', (function(marker, index)
{
return function()
{
infowindow.close(map,marker);
infowindow.setContent(e[index][0]);
infowindow.open(map, marker);
}
})(marker, index));
});
}
}).done(function(){
jQuery('#loading').hide();
});
Use this library to manage marker clustering and it would help optimize your map view (this answer should help integrate).
Also, the code in the snippet works well with filtering usually. You can try it out. Might just do the trick.
// Get all markers from the php document markers.php ( output
simulates json object )
$('#map-canvas').gmap().bind('init', function(evt, map) {
$.getJSON( 'http://example.php',
function(data) { $.each( data.markers, function(i, marker) {
$('#map-canvas').gmap('addMarker', {'tags': marker.tags, 'position': new google.maps.LatLng(marker.latitude, marker.longitude),'bounds': true}).click(function() {
// Declares what you want to show in the info window when marker is clicked
$('#map-canvas').gmap('openInfoWindow', { 'content': '<strong>' +
marker.title + '</strong><br/>' + marker.address + '<br/>' +
marker.phone + '<br/><br/>' + marker.tags }, this);
});
// Filter map
$('#map-canvas').gmap('find', 'markers', { 'property': 'tags',
'value': ['baths', 'bedrooms', 'minprice', 'maxprice'], 'operator':'AND' }, function(marker, isFound) {
if ( isFound ) {
marker.setVisible(true);
} else {
marker.setVisible(false);
}
});
});
});
}); // End map function

Google Maps Api v3, marker load from XML, not show on map

I have a big problem with Google Maps Api and jQuery.
I need get markers from XML file, and show on map.
This is page with map:
http://szymonnosal.pl/sandbox/bsk/
And my code:
I initialize map:
var mapa; // obiekt globalny
var dymek; // okno z informacjami
var networks = [];
var locations = [];
function mapaStart()
{
var wspolrzedne = new google.maps.LatLng(50.0157021545812, 19.9094574787954);
var opcjeMapy = {
zoom: 15,
center: wspolrzedne,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true,
navigationControl: true,
mapTypeControl: true
};
mapa = new google.maps.Map(document.getElementById("mapka"), opcjeMapy);
dymek = new google.maps.InfoWindow();
loadNetworks();
google.maps.event.addListener(mapa,'click',function(){
resetLocations();
});
}
In loadNetwork() I load marker from XML file, I using jQuery:
function loadNetworks()
{
$.get('net.xml',function(xml){
$(xml).find("network").each(function(){
var lat = parseFloat($(this).find("lat").text());
var lon = parseFloat($(this).find("lon").text());
var icon_url = $(this).find("icon").text();
var SSID = $(this).find("SSID").text();
var BSSID = $(this).find("BSSID").text();
var AuthMode = $(this).find("AuthMode").text();
var Frequency = $(this).find("Frequency").text();
//alert(lat+' '+lon+' '+icon_url+' '+SSID+' '+BSSID+' '+AuthMode+' '+Frequency);
var marker = addNetwork(lat,lon,icon_url,SSID,BSSID,AuthMode,Frequency);
alert(marker.txt); // <- marker is correct object, because in alert pop-up is text from marker.
});
});
}
And in addNetwork I add marker on map.
function addNetwork(lat,lon,icon_url,SSID,BSSID,AuthMode,Frequency)
{
var size = new google.maps.Size(30,23);
var start_point = new google.maps.Point(0,0);
var start_hook = new google.maps.Point(15,12);
var icon = new google.maps.MarkerImage(icon_url, size, start_point, start_hook);
var marker = new google.maps.Marker(
{
position: new google.maps.LatLng(lat,lon),
title: BSSID,
icon: icon,
map: mapa
}
);
marker.txt = 'BSSID: '+BSSID+'<br/>SSID: '+SSID+'<br />AuthMode: '+AuthMode+'<br />Frequency: '+Frequency;
google.maps.event.addListener(marker,"click",function()
{
dymek.setPosition(marker.getPosition());
dymek.setContent(marker.txt);
dymek.open(mapa);
});
return marker;
}
If i use other function to load XML, it's correct:
function loadNetworks()
{
jx.load('getNetwork.php', function(xml)
{
var markery = xml.getElementsByTagName("network");
for(var i=0; i<markery.length; i++)
{
var lat = parseFloat(markery[i].attributes.getNamedItem("lat").nodeValue);
var lon = parseFloat(markery[i].attributes.getNamedItem("lon").nodeValue);
var ikona_url = markery[i].attributes.getNamedItem("ikona").nodeValue;
var SSID = markery[i].attributes.getNamedItem("SSID").nodeValue;
var BSSID = markery[i].attributes.getNamedItem("BSSID").nodeValue;
var AuthMode = markery[i].attributes.getNamedItem("AuthMode").nodeValue;
var Frequency = markery[i].attributes.getNamedItem("Frequency").nodeValue;
var marker = addNetwork(lat,lon,ikona_url,SSID,BSSID,AuthMode,Frequency);
}
alert('Wczytano '+markery.length+' markerów z pliku networks.xml');
},'xml','get');
}
jx is function from: http://www.openjs.com/scripts/jx/
Do You have any idea, what is wrong in my code?
Looks to me like the icon_url is not defined. A test would be to change the marker definition to:
var marker = new google.maps.Marker(
{
position: new google.maps.LatLng(lat,lon),
title: BSSID,
// icon: icon,
map: mapa
});
This is on the live site:
var icon_url = jQuery(this).find("icon").text();
Not this (which is your posted code):
var ikona_url = markery[i].attributes.getNamedItem("ikona").nodeValue;
Your xml uses "ikona", and is the content of the element not an attribute.
<networks>
<network>
<lat>50.0158556853</lat>
<lon>19.9096229322</lon>
<SSID>untitled</SSID>
<BSSID>f0:7d:68:48:97:00</BSSID>
<AuthMode>[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][ESS]</AuthMode>
<Frequency>2447</Frequency>
<ikona>http://maps.google.com/intl/en_us/mapfiles/ms/micons/green.png"</ikona>
</network>
</networks>
Is there a way you can convert XML to JSON as returned data?
If yes, then try vMap.
vMap is a lightning jQuery plugin with HTML 5 that makes Google Maps easy by sending a simple JSON Data Structure.
https://github.com/vhugogarcia/vMap
It helped me to solve a lot the markers problem with Google Maps, but also adds the feature for listing the locations if needed.
Feel free to modify it as your needs.

Adding Markers on Google Map

I'm trying to update a marker in real time on a Google Map. I need a marker for the starting location and then as the location changes (the user moves) a polyline will be drawn and a marker will show the current location. So, for each user there will be two markers; one showing the start location and one that keeps updating and showing the current location.
I can get the lines drawn and the start marker to work, but with this code each time the location changes, a new marker is placed instead of the old one being updated. I'm trying to use setPosition(); but it doesn't seem to work. Any thoughts?
function initialize() {
var myLatlng = new google.maps.LatLng(39, -86);
var myOptions = {
zoom: 6,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var loc = {};
var mark = {};
var markers = {};
$(function () {
$(document).ready(function(){
setInterval(function(){
$.ajax({
url: 'api.php', //the script to call to get data
//data: "",
dataType: 'json', //data format
success: function(data){ //on recieve of reply
var user_id = data[0];
var lati = data[1]; //get id
var longi = data[2]; //get name
var myLatlngt = new google.maps.LatLng(lati, longi);
if (typeof loc[user_id] === 'undefined') {
loc[user_id] = [];
}
//if (typeof markers[user_id] === 'undefined') {
//markers[user_id] = [];
//}
if (typeof mark[user_id] === 'undefined') {
mark[user_id] = myLatlngt;
}
loc[user_id].push(myLatlngt);
//markers[user_id].push(myLatlngt);
var marker1;
var x;
for (x in loc) {
var polyline = new google.maps.Polyline({
map: map,
path: loc[x],
strokeColor: "#FF0000",
strokeOpacity: 1.0,
strokeWeight: 2
});
polyline.setMap(map);
///location variables
var start_loc = loc[user_id];
var start_marker = start_loc[0]; //start location of given user
var current_loc = start_loc[start_loc.length -1]; //last known location of given user
//set the start marker
var marker = new google.maps.Marker({
position: start_marker,
title: user_id
});
marker.setMap(map);
//update the current location marker
if (marker1 != null) {
marker1.setPosition(current_loc);
}
else {
marker1 = new google.maps.Marker({
position: current_loc,
map: map
});
}
}
//console.log('location :::', x);
console.log('Marker: ', mark);
}
});
}, 1000);
});
});
}
Try declaring your marker1 variable (var marker1;) outside the function to make it global (scope). Right after var markers = {}; should do it. Let me know if this does not work, and I will look in to it deeper.

Categories

Resources