Mapbox Polyline too complex, maybe? - mapbox

I am using Mapbox API to locate two gps locations and draw a polyline between them. The code that I have written works...sometimes.
It seems that if the two locations are physically close to each other it works more often than not, but if the two points are further away then it doesn't work more often than not, but I can't duplicate the results consistently. My working theory right now is that the polyline gets too complex for the API to decode. Is there a way to simplify a polyline or request a simpler one in the first place?
I've marked the line in the code below that is problematic. Does anyone have any ideas why it sometimes works and sometimes doesn't???
If it matters, my ultimate goal with this is generating a static map image that will be used in a report, so I'm not really worried about bandwidth or efficiency, I just need the image to work.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=<device-width>, initial-scale=1.0">
<title>Document</title>
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous">
</script>
<script src="js/jquery.fileDownload.js"></script>
<script>
//Declare Variables
var token = "myuniquetoken";
var longitude;
var latitude;
var longitude2;
var latitude2;
var polyline;
//When first Get GPS Button is Pressed
$(document).ready(function() {
$("#btnGetGPS").click(function(){
var address = $("#address").val();
var addressstring = address.replace(" ", "%20");
var url = "https://api.mapbox.com/geocoding/v5/mapbox.places/" + addressstring + ".json?access_token=" + token;
var jqxhr = $.getJSON( url, function(data) {
longitude = data["features"][0]["center"][0];
latitude = data["features"][0]["center"][1];
$("#gpslong").text(longitude);
$("#gpslat").text(latitude);
var mapPinUrl = "https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-l+000(" + longitude + "," + latitude + ")/" + longitude + "," + latitude + ",14/500x300?access_token=" + token;
$('#mapDiv').html('<img id="mapImg" src=' + mapPinUrl +' />');
$('#secondlocation').show();
});
});
});
//When second Get GPS Button is Pressed
$(document).ready(function() {
$("#btnGetGPS2").click(function(){
var address2 = $("#address2").val();
var addressstring2 = address2.replace(" ", "%20");
var url2 = "https://api.mapbox.com/geocoding/v5/mapbox.places/" + addressstring2 + ".json?access_token=" + token;
var jqxhr2 = $.getJSON( url2, function(data) {
longitude2 = data["features"][0]["center"][0];
latitude2 = data["features"][0]["center"][1];
$("#gpslong2").text(longitude2);
$("#gpslat2").text(latitude2);
//Get a polyline
var polyURL = "https://api.mapbox.com/directions/v5/mapbox/driving/" + longitude + "," + latitude + ";" + longitude2 + "," + latitude2 + "?access_token=" + token;
console.log(polyURL);
var polyJSON = $.getJSON( polyURL, function(data2) {
polyline = data2["routes"][0]["geometry"];
console.log(polyline);
//////////////////The next line is the problematic one.//////////////////
var mapRoute = "https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(" + longitude + "," + latitude + "),pin-s-b+000(" + longitude2 + "," + latitude2 + "),path-5+f44-0.5(" + polyline + ")/auto/500x300?access_token=" + token;
console.log(mapRoute);
$('#mapDiv2').html('<img id="mapImg" src=' + mapRoute +' />');
});
});
});
});
</script>
</head>
<body>
Enter an address (i.e. 1600 Pennsylvania Avenue NW, Washington, DC 20500):</br>
<input id="address"/></br>
<button id="btnGetGPS" type="button">Get GPS</button>
<div id = "gpslong"></div>
<div id = "gpslat"></div>
<div id="mapDiv"></div>
<div id="secondlocation" style="display:none">
Enter a second location:
<input id="address2"/></br>
<button id="btnGetGPS2" type="button">Get GPS</button>
<div id = "gpslong2"></div>
<div id = "gpslat2"></div>
<div id="mapDiv2"></div>
</div>
</body>
</html>

I'm leaving this question up and proving the answer that someone helped me discover in hopes of helping other people in the future.
.
The problem was that the polyline I was getting in the first API request contained special characters like `,~,|, etc. When I tried to use that same string in the second API request, those special characters were sometimes causing problems. I added the line of code below to scrub out those special characters and replace them with safe ASCII.
.
polyline = encodeURIComponent(polyline);

Related

Leaflet Add Marker on click with pop up of lat lng coordinates?

I would like the ability to click on my map and have the following happen:
Add a temporary marker to the map that will display the lat lng coordinates of that marker.
This should help
<script src="https://cdn.jsdelivr.net/npm/leaflet#1.3.4/dist/leaflet-src.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/leaflet-extra-markers#1.0.6/src/assets/js/leaflet.extra-markers.min.js"></script>
<body>
...
<div id="carteDiv"> </div>
</body>
<script>
// Map object
var m_Carte = L.map('carteDiv').setView([45.469717, -73.563719], m_Zoom);
// Create click event handler
m_Carte.on('click', onMapClick);
// The function to create marker on click
var onMapClick = function (e) {
var marqueur = L.marker([e.latlng.lat, e.latlng.lng], {
icon : L.ExtraMarkers.icon({
icon : 'fa-number',
prefix : 'fa',
markerColor : red,
number : 0
})
}).addTo(m_Carte).bindPopup(e.latlng.lat + ' ' + e.latlng.lng);
};
</script>

leaflet marker cluster icons not displaying

I have a problem where the marker clusters work and show the number of items in the cluster, however the icons don't show up. When I zoom in, individual icons show, but from far away the cluster icons don't. Here's the code where I set up the data in the cluster:
// Marker cluster
var producerLayer = new L.MarkerClusterGroup();
// Loop through the lp array
for (var i=0; i < lp.length; i++) {
var name = lp[i][0];
var place = lp[i][1];
var lat = lp[i][2];
var lng = lp[i][3];
var liscence = lp[i][4];
var risk = lp[i][5];
var icon = greenIcon;
var markerLocation = new L.LatLng(lat, lng);
var marker = new L.Marker(markerLocation, {icon});
var content = '<div class="info_content">' +
'<h3>' + name + '</h3>' +
'<p>' + place + '</p>' +
'<p>' + 'Date of initial liscencing: ' + liscence + '</p>' +
'<p>' + 'Risk rating: ' + risk + '</p>';
producerLayer.addLayer(marker);
marker.bindPopup(content).openPopup();
}
producerLayer.addTo(map);
I have attached an image below of the problem that I'm having.
Looks like you are just missing the Leaflet.markercluster plugin CSS files, as described on the plugin docs:
[…] use files in the dist folder:
MarkerCluster.css
MarkerCluster.Default.css (not needed if you use your own iconCreateFunction instead of the default one)
leaflet.markercluster.js (or leaflet.markercluster-src.js for the non-minified version)
For example using unpkg.com CDN:
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster#1.3.0/dist/MarkerCluster.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster#1.3.0/dist/MarkerCluster.Default.css">

Leaflet Pan Event (moveend) is not working

I am trying to update two fields from database if map pan based on it longlat position. I am using the following code
map.on("moveend", function () {
var cntLat = map.getCenter().lat;
var cntLong = map.getCenter().lng;
var zoomScale = map.getZoom();
$.ajax({
type: "GET",
url: 'panevent.php?&zoom=' + zoomScale + '&getLat=' + cntLat + '&getLong=' + cntLong,
success: function (result) {
var JSONobject = JSON.parse(result);
var title = JSONobject[0]["title"];
var subtitle = JSONobject[0]["subtitle"];
$("title").html(title);
$("subtitle").html(subtitle);
}});
});
Here is my HTML Block
<div class="currentLoc">
<p id="title"></p>
<p id="subtitle"></p>
</div>
What I am doing wrong?
L.Map does fire dragend. You have to use moveend
dragend is for draggable L.Marker

Google Chart - Using Spreadhseet Source does not resolve

Using the tutorial from google on using a spreadsheet as data for a chart I have created the following.
Tutorial
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {packages: ['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawSheetName() {
var query = new google.visualization.Query('https://docs.google.com/spreadsheets/d/15l3ZK45hv2ByOfkUiAKoKp-Z9a1u1-Q_rsLS7SqC51E/editgid=0&headers=1');
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(data, { height: 400 });
}
}}
</script>
</head>
<body>
<!-- Identify where the chart should be drawn. -->
<div id="chart_div"/>
</body>
However no chart resolves, I have made the link public.
If I share the link it is https://docs.google.com/spreadsheets/d/15l3ZK45hv2ByOfkUiAKoKp-Z9a1u1-Q_rsLS7SqC51E/edit?usp=sharing
Following the docs and not sure where my error is.
This SO answer more about drive-sdk creates the key from a script from a new file, I don't really understand it and nuclear how you can obtain the correct URL for existing spreadsheets.
Would be great if there could be a consolidated answer obtaining correct sheets URL's.
Is this what you are trying to achieve?
If yes, you can check how it works here.
EDIT
Since I notice in the comments you want to query the spreadsheet and not use the entire spreadsheet, this is the logic to query with.
First, these are the basic components of the url to query:
var BASE_URL = "https://docs.google.com/a/google.com/spreadsheets/d/";
var SS_KEY = "stringSS_Key";
var BASE_QUERY = "/gviz/tq?tq=";
var partialUrl = BASE_URL + SS_KEY + BASE_QUERY;
Notice the BASE_QUERY variable
The first bit of the url is in the partialUrl variable.
Then, you need to use the Query Language that google provides. An example would be:
var queryToRun = 'select dept, sum(salary) group by dept';
You then need to call encodeURIComponent() on it, and add it to the partial URL. The final URL then becomes
var finalUrl = partialUrl + encodeURIComponent(queryToRun);
Only then you can run the google.visualiation.query as I suspect you intend.
var query = new google.visualization.Query(finalUrl);

web audio soundcloud crossfade

I'm struggling to get this basic fade-in / fade-out Web Audio code to work with SoundCloud. It appears that the gainNode.gain.linearRampToValueAtTime functions are bypassed (ie, play starts and ends at gain.volume = 1.0.)
Code needs to work with iOS mobile Safari webkit.
CSS included:
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>
HTML Follows:
<div id="wrapper">
<div id="content">
<div class="post">
<h2>Fading in a Soundcloud Track</h2>
</p>
</div>
</div>
</div>
JS Follows:
<script>
var audioCtx = new (window.AudioContext ||
window.webAudioContext ||
window.webkitAudioContext)();
var audio = new Audio();
var url = 'https://api.soundcloud.com/tracks/179612876/stream' + '?client_id=<MY_ID>';
audio.src = url;
audio.preload = true;
audio.load();
audio.addEventListener('canplay', function(){
var currTime = audioCtx.currentTime;
var duration = 30;
var fadeTime = 6;
var gainNode = audioCtx.createGain();
gainNode.gain.value = 0.0;
var source = audioCtx.createMediaElementSource(audio);
source.connect(gainNode);
gainNode.connect(audioCtx.destination);
// Then fade in
gainNode.gain.linearRampToValueAtTime(0.0, currTime);
gainNode.gain.linearRampToValueAtTime(1.0, currTime + fadeTime);
// Then fade it out.
gainNode.gain.linearRampToValueAtTime(1.0, currTime + duration-fadeTime);
gainNode.gain.linearRampToValueAtTime(0.0, currTime + duration);
//source.connect(audioCtx.destination);
source.mediaElement.play();
},false);
</script>
"gainNode.gain.value = 0.0;" doesn't actually set a schedule point in the scheduler, it just sets the current value. Since there's no start point in the scheduler, it's jumping up when it hits the first schedule point (i.e. at time currTime + fadeTime). Try this:
gainNode.gain.setValueAtTime(0.0, currTime);
gainNode.gain.linearRampToValueAtTime(1.0, currTime + fadeTime);
// Then fade it out.
gainNode.gain.setValueAtTime(1.0, currTime + duration-fadeTime);
gainNode.gain.linearRampToValueAtTime(0.0, currTime + duration);
(and don't bother setting gain.gain.value).