Mapbox GL JS - Reverse Geocoding with coordinates - javascript

I have a map done on mapbox gl js.
I'm trying to get a placename / address by reverse geocoding longitude and latitude coordinates.
I can manage to get normal forward geocoding to work but querying the following (for example):
geocoder.query('New York')
But i cant quite figure out how to do this in reverse with coordinates. I've tried the following to no avail:
// geocoder.query(126.981,37.539)
// geocoder.query("126.981,37.539")
// geocoder.query(37.539,126.981)
// geocoder.query("37.539,126.981")
I couldnt find anything in the documents to point me in the right direction as well. Thus any help is greatly appreciated.
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Set a point after Geocoder result</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.49.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.49.0/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
.built_address {
position: fixed;
top: 0;
left: 0;
background-color: white;
padding: 10px;
font-size: 12px;
font-family: Arial;
}
</style>
</head>
<body>
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.3.0/mapbox-gl-geocoder.min.js'></script>
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v2.3.0/mapbox-gl-geocoder.css' type='text/css' />
<style>
#geocoder-container > div {
min-width:50%;
margin-left:25%;
}
</style>
<div id='map'></div>
<div class="built_address">LOREM IPSUM</div>
<script>
var built_address = '';
var user_coordinates;
var geocode_results;
mapboxgl.accessToken = 'pk.eyJ1IjoiZmFyaXNrYXNzaW0iLCJhIjoiSk1MaUthdyJ9.vkxtdDbYdLi524WwlKORBw';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/fariskassim/cjmszx78b266o2rlar02ytynj',
center: [127.017768, 37.59837],
zoom: 12
});
var geocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken
});
map.addControl(geocoder);
// After the map style has loaded on the page, add a source layer and default
// styling for a single point.
map.on('load', function() {
map.addSource('single-point', {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": []
}
});
map.addLayer({
"id": "point",
"source": "single-point",
"type": "circle",
"paint": {
"circle-radius": 10,
"circle-color": "#007cbf"
}
});
getUserLocation();
});
function getUserLocation() {
// request to allow user position
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
function showPosition(position) {
// get user current coordinates and center map on coordiates
console.log('L2', position)
//console.log(position.coords.latitude, position.coords.latitude)
user_coordinates = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
// draw user location on mao
map.getSource('single-point').setData({type: "Point", coordinates: [user_coordinates.lng,user_coordinates.lat]});
// geocoder.query(user_coordinates.lat, user_coordinates.lng)
// Listen for the `result` event from the MapboxGeocoder that is triggered when a user
// makes a selection and add a symbol that matches the result.
geocoder.on('result', function(ev) {
map.getSource('single-point').setData(ev.result.geometry);
console.log('ev',ev)
built_address = ev.result.place_name
});
}
} else {
// if device doesnt support location
console.log('device doesnt support location')
}
}; /* END getUserLocation(); */
</script>
</body>
</html>

Try geocoder.mapboxClient.geocodeReverse:
geocoder.mapboxClient
.geocodeReverse({
latitude: user_coordinates.lat,
longitude: user_coordinates.lng
}, function(err, res) {
console.log(err, res)
});
Update
mapbox-gl-geocoder v5.0.0
You have to create a geocoder with reverse geocoding enabled :
let geocoder = new MapboxGeocoder({
accessToken:mapboxgl.accessToken,
mapboxgl:mapboxgl,
reverseGeocode:true
})
Then you will be able to do :
geocoder.query("126.981,37.539")
...
Be aware that the default coordinates format is lat,lng but you can invert it with the options.flipCoordinates

Related

store users geolocation in 30 second intervals

I'm trying to figure out how I can refactor my code so that I can send a user's geolocation to my MySQL database in 30 second intervals.
This code below store's a users geolocation in the table only when the application is loaded or if the application is refreshed but It does not continuously store the geolocation as the person travels. I am looking to send the users geolocation to the server periodically in 30 second bursts.
I am aware of jquery setInterval and have tried to nest it in several places without success as javascript is rusty.
Any steering would be greatly appreciated.
My Table Schema
heatmap.php
<?php require_once("../resources/config.php"); ?>
<!DOCTYPE html>
<html>
<head>
<title>FOX COUNT</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="css/heatmapstyle.css">
<style>
/* NOTE: GOOGLE MAPS NEEDS HTTPS TO WORK. IT WILL NOT WORK WITH HTTP AKA UNSECURE ORIGIN */
#map {
height: 100%;
}
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map">
<!--Google map will be embedded here-->
</div>
<script>
var map, currentPositionMarker, map;
function initializeMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 16,
});
}
function locError(error) {
// tell the user if the current position could not be located
alert("The current position could not be found!");
}
// current position of the user
function setCurrentPosition(pos) {
currentPositionMarker = new google.maps.Marker({
label: {
color: 'black',
fontWeight: 'bold',
text: 'CD',
},
map: map,
position: new google.maps.LatLng(
pos.coords.latitude,
pos.coords.longitude,
),
title: "Current Position"
});
var a = pos.coords.latitude;
var b = pos.coords.longitude;
console.log(a, b);
// This ajax command stores the lat and lang into the db ONLY when the app loads from fresh or if the app refreshes. It DOES NOT continously store the users geolocation when ever the user marker changes geolocation. !!!
$.ajax({
type: "GET",
url: "personlocator.php",
data: {
a: a,
b: b
}
})
map.panTo(new google.maps.LatLng(
pos.coords.latitude,
pos.coords.longitude
));
} // end of function ///////////////////////////
function watchCurrentPosition(pos) {
var positionTimer = navigator.geolocation.watchPosition(
function(position) {
setMarkerPosition(
currentPositionMarker,
position
);
});
}
function setMarkerPosition(marker, position) {
marker.setPosition(
new google.maps.LatLng(
position.coords.latitude,
position.coords.longitude)
);
}
function initLocationProcedure() {
initializeMap();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(setCurrentPosition, watchCurrentPosition, locError);
} else {
// tell the user if a browser doesn't support this amazing API
alert("Your browser does not support the Geolocation API!");
}
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY_IS_NESTED_HERE&libraries=visualization&callback=initLocationProcedure">
</script>
<!--javascript and jquery CDN's directly beneath here-->
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
</body>
</html>
personlocator.php
if (isset($_GET['a'], $_GET['b'])) {
$latitude = escape_string($_GET['a']);
$longitude = escape_string($_GET['b']);
$updateQuery = $mysqli->query("UPDATE users
SET user_latitude='$latitude'
, user_longitude='$longitude'
WHERE id= '{$id}' ");
mysqli_query($connection,$updateQuery);
confirm($updateQuery);
redirect("personlocator.php");
}
You can nest it like this:
function initLocationProcedure() {
initializeMap();
if (navigator.geolocation) {
// Timer with setInterval
var timer = setInterval( function() {
navigator.geolocation.getCurrentPosition(setCurrentPosition, locError);
}, 30000);
} else {
// tell the user if a browser doesn't support this amazing API
alert("Your browser does not support the Geolocation API!");
}
}

WMTSLayers seems not working in EPSG:25830

I'm developing new web and I want to consume WMTS services with ArcGIS javascript API4
WMTSLayer in Javascript API 4.11 seems not working when spatialReference EPSG:25830 is selected.
The problem is that the request is generating by the API is incorrect, Tilerow parameter is wrong.
The request is being sent is this. http://www.ign.es/wmts/ign-base?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=IGNBaseTodo&STYLE=default&FORMAT=image%2Fjpeg&TILEMATRIXSET=EPSG%3A25830&TILEMATRIX=18&TILEROW=236256&TILECOL=32268
And must be...
http://www.ign.es/wmts/ign-base?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=IGNBaseTodo&STYLE=default&FORMAT=image%2Fjpeg&TILEMATRIXSET=EPSG%3A25830&TILEMATRIX=18&TILEROW=32374&TILECOL=32268
Here is my code example.
JSFIDDLE
or
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<link
rel="stylesheet"
href="https://js.arcgis.com/4.11/esri/themes/light/main.css"
/>
<title>Select WMTSLayer sublayer - 4.11</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 95%; /* allow space for sublayer switcher */
width: 100%;
}
select,
label {
font-family: "Avenir Next W00", "Helvetica Neue", Helvetica, Arial,
sans-serif;
}
#selectDiv {
background-color: lightgrey;
padding: 10px;
}
#theLabel {
visibility: hidden; /* hide until populated */
}
.esri-layer-list {
width: 310px;
}
</style>
<script src="https://js.arcgis.com/4.11/"></script>
<script>
var map, view;
require([
"esri/Map",
"esri/Basemap",
"esri/Viewpoint",
"esri/geometry/Extent",
"esri/views/MapView",
"esri/layers/WMTSLayer",
"esri/widgets/LayerList",
"esri/core/watchUtils"
], function(
Map,
Basemap,
Viewpoint,
Extent,
MapView,
WMTSLayer,
LayerList,
watchUtils
) {
var layerBase = {baseMapLayers: [{id: "basemap-layer", opacity: 1, title: "aaaaa", url: "http://arcgis.bizkaia.eus/arcgis/rest/services/ORTOFOTOS/GOBIERNO_VASCO_2016_AMPLIADO/MapServer", visibility: true, layerType:"ArcGISTiledMapServiceLayer"}], title: "Basemap"}
layer = new WMTSLayer({
url: "http://www.ign.es/wmts/ign-base"
});
map = new Map({
basemap: Basemap.fromJSON(layerBase),
});
view = new MapView({
container: "viewDiv",
map: map
});
view.when(function() {
layerList = new LayerList({
view: view
});
view.ui.add(layerList, "bottom-left");
layer.load();
layer.when(function() {
// add all sublayers to the select element
layer.sublayers.forEach(function(sublayer, i) {
if (sublayer.id === "IGNBaseOrto" || sublayer.id === "IGNBaseTodo" )
selectSublayer.options[ selectSublayer.options.length ] = new Option("(" + i + ") " + sublayer.title, sublayer.id);
});
// once populated, show the select element
var theDiv = document.getElementById("theLabel");
theDiv.style.visibility = "visible";
}); // end layer.load function
});
// if sublayer is changed, recreate map, view, and widgets using new activeLayer
document.getElementById("selectSublayer").onchange = function(event) {
map.removeAll();
if(event.target.value!==""){
layer.activeLayer = layer
.findSublayerById(event.target.value)
.clone();
map.layers.add(layer);
}
};
});
</script>
</head>
<body>
<div id="selectDiv">
<label id="theLabel">
Pick a layer from the WMTS catalog
<select id="selectSublayer"><option value="">No Layers Selected</option></select>
</label>
</div>
<div id="viewDiv"></div>
</body>
</html>
To reproduce the error one of the WMTSLayer must be selected from the select box.
There is a workaround to solve this problem?
Your basemap layer type is ArcGISTiledMapServiceLayer, which in the new API 4.11 is a TileLayer.
According to the documentation of the TileLayer from ESRI:
https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-TileLayer.html
Known Limitations
When adding a TileLayer to a map in a SceneView, the following
limitations exist:
This layer needs to be published from ArcGIS Server 10.3 and later or
ArcGIS Server 10.2.2 with this applied fix. If viewingMode is global,
then only services with ArcGIS Online/Bing Maps/Google Maps (Web
Mercator) or WGS84 Geographic Coordinate System, Version 2 tiling
scheme are supported. If viewingMode is local, then only services with
projected coordinate systems are supported. Only Tile layers with the
following tiling scheme specifications are supported:
256x256 or 512x512 pixel tiles Scale levels must increase or decrease
by a power of two At level 0 there shouldn't be more than 30 root
tiles. All tiled layers must have the same tiling scheme and
SpatialReference.
Please find the fiddle here and example which does not work but does not fail either (does not show 400 bad request when loading the layer)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<link
rel="stylesheet" href="https://js.arcgis.com/4.11/esri/themes/light/main.css"
/>
<title>Select WMTSLayer sublayer - 4.11</title>
<style>
html,body,
#viewDiv {
padding: 0;
margin: 0;
height: 95%; /* allow space for sublayer switcher */
width: 100%;
}
select, label {
font-family: "Avenir Next W00", "Helvetica Neue", Helvetica, Arial,
sans-serif;
}
#selectDiv {
background-color: lightgrey;
padding: 10px;
}
#theLabel {
visibility: hidden; /* hide until populated */
}
.esri-layer-list {
width: 310px;
}
</style>
<script src="https://js.arcgis.com/4.11/"></script>
<script>
var map, view, layer;
require([
"esri/Map",
"esri/Basemap",
"esri/views/MapView",
"esri/layers/WMTSLayer",
"esri/widgets/LayerList",
"esri/layers/TileLayer"
], function(Map,Basemap,MapView,WMTSLayer,LayerList,TileLayer) {
var basemap = new Basemap({
baseLayers: [
new TileLayer({
url: "http://arcgis.bizkaia.eus/arcgis/rest/services/ORTOFOTOS/GOBIERNO_VASCO_2016_AMPLIADO/MapServer"
})]
});
var layerBase = {
title: "Basemap",
baseMapLayers: [{
url: "http://arcgis.bizkaia.eus/arcgis/rest/services/ORTOFOTOS/GOBIERNO_VASCO_2016_AMPLIADO/MapServer",
visibility: true,
layerType:"ArcGISTiledMapServiceLayer"}]};
layer = new WMTSLayer({
url: "http://www.ign.es/wmts/ign-base"
});
map = new Map({
//basemap: Basemap.fromJSON(layerBase),
//basemap: "streets",
basemap: basemap,
layers: [layer]
});
view = new MapView({
container: "viewDiv",
map: map
});
view.when(function() {
view.extent = layer.fullExtent;
var layerList = new LayerList({
view: view
});
view.ui.add(layerList, "bottom-left");
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
I think the problem is in the reference system (which is readonly), the above layer is not re-projected to fit over the basemap.
In this image you can check what projections are supported on IGNBaseTodo layer the layer that I am trying to use.
I have load this layer on QGIS with EPSG:28530 spatial reference and I have captured the requests and compare with the requests that arcgis API4 is doing, the unique difference is tilerow parameter, everything else is ok.
image

Adding multiple markers with Google Maps API [duplicate]

This question already has answers here:
Google Maps JS API v3 - Simple Multiple Marker Example
(15 answers)
Closed 4 years ago.
I am trying to use Google maps API for a website and I can't seem to get multiple locations to populate like Google has it in their example.
Could anyone please let me know what I need to add to get 11 markers to show up that will give a description of what I want.
I can see that Google has multiple locations giving a quick description of what they are.
PS: I already have a key I just need to know how to include "X" number of markers with a description attached.
Attached is the link to googles example:
Google Maps API
Here is the code:
<!DOCTYPE html>
<html>
<head>
<title>Place searches</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
var map;
var infowindow;
function initMap() {
var pyrmont = {lat: -33.867, lng: 151.195};
map = new google.maps.Map(document.getElementById('map'), {
center: pyrmont,
zoom: 15
});
infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: pyrmont,
radius: 500,
type: ['store']
}, callback);
}
function callback(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
</script>
</head>
<body>
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initMap" async defer></script>
</body>
</html>
You need to try this:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Simple markers</title>
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
function initMap() {
var myLatLng = {
lat: -25.363,
lng: 131.044
};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: myLatLng
});
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: 'Hello World!'
});
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

google api using javascript

var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: 30.3434,
lng: 30.234
},
zoom: 8
});
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=&callback=initMap" async defer></script>
how to input coordinates to google api java script automatically ?!
here is the code
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat:30.3434, lng:30.234},
zoom: 8
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=&callback=initMap"
async defer></script>
</body>
</html>
i want to the "center" to take the coordinates from a txt file at my pc at as a test
Assuming your file is location.txt and the content is something like:
lat;long, e.g. 30.3434;30.234
You can do what you want using jQuery:
function initMap() {
var myLat, myLng, myMap;
$.ajax({
url : "location.txt",
dataType: "text",
success : function (data) {
var location = data.split(";");
myLat=location[0];
myLng=location[1]
},
error: function(data) {
console.log("unable to retrieve data from location.txt")
},
complete: function(data) {
//Called after success and error callbacks are executed.
myMap = new google.maps.Map(document.getElementById('map'), {
center: {lat:myLat, lng:myLng},
zoom: 8
});
}
});
}

Manually setting basemap using ArcGIS API for JavaScript?

Looked over the example can NOT figure out how to set basemap MANUALLY. I don't want a dijit widget, or any other libraries or anything like that. Just want to manually set a basemap to any of the already available types like Topographic, Satellites, Streets, etc.
Following this API reference:
Object: esri/basemaps
The part I can't figure out is marked with question marks. If some could help me out, would really appreciate it.
require([
"esri/basemaps",
"esri/map",
"dojo/domReady!"
], function (esriBasemaps, Map) {
/* ------------------------------------- */
/* Basemap add one of the existing maps. */
/* ------------------------------------- */
esriBasemaps.myBasemap = {
baseMapLayers ???
};
var map = new Map("map", {
basemap: "myBasemap",
center: [-118, 34.5],
zoom: 8
});
});
The code in the esri/basemaps documentation works fine, combined with the create a map sample.
Here's the part you wondered about:
esriBasemaps.myBasemap = {
baseMapLayers: [
{
url: "http://services.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer"
}
],
title: "My Basemap"
};
Here's a full example. Copy and paste the following into the ArcGIS API for JavaScript Sandbox to see how it works.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
<title>Simple Map</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.13/esri/css/esri.css">
<style>
html, body, #map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
body {
background-color: #FFF;
overflow: hidden;
font-family: "Trebuchet MS";
}
</style>
<script src="http://js.arcgis.com/3.13/"></script>
<script>
var map;
require(["esri/basemaps", "esri/map", "dojo/domReady!"], function(esriBasemaps, Map) {
esriBasemaps.myBasemap = {
baseMapLayers: [
{
url: "http://services.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer"
}
],
title: "My Basemap"
};
map = new Map("map", {
basemap: "myBasemap",
center: [-122.45, 37.75], // longitude, latitude
zoom: 13
});
});
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>

Categories