# Exact GeoPosition from FormFunction

Posted 3 years ago
5310 Views
|
4 Replies
|
7 Total Likes
|

# Backstory

When trying to set up a system to collect birdwatching data from the public, I was recently faced with the problem of collecting accurate locations from people filling in the form. The obvious choice is to use Here, but the accuracy, especially on laptops was just not enough.

I reached out to Christopher Wolfram and Carlo Barbieri for support and together (large parts of the code contained here is their doing) we were able to create an intuitive and functional solution that let us combine the FormFunction with embedded HTML code and JavaScript accessing the Google Maps API. Many things about the code can be adjusted, like whether you drag the map or the marker and many more, but it has already been extremely useful for my purpose, so I thought I should share with the community.

# The code

First, we need to set up the function we are going to call on that consists of HTML and Javascript embedding the map.

    apiKey="Your_API_key";
mapControl[apiKey_, name_, defaultPosition_, defaultZoom_:15]:= Function[EmbeddedHTML@StringTemplate["
<input type=\"hidden\" id=\"mapField\" name=\"Name\">
<div id=\"selectionMap\" style=\"width:100%;height:400px;\"></div>
<script>
field = document.getElementById(\"mapField\")
function initMap() {
defaultPosition = {lat: Latitude, lng: Longitude}
document.getElementById(\"selectionMap\"),
{zoom: DefaultZoom, center: defaultPosition})
position: defaultPosition,
draggable:false,
map: map
})
field.value = marker.position
map,
\"center_changed\",
function() {
marker.setPosition(map.getCenter())
field.value = marker.position
}
)

function showPosition(position) {
coords = {
lat: position.coords.latitude,
lng: position.coords.longitude
}
marker.setPosition(coords)
map.panTo(coords)
field.value = marker.position
}
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, console.log, {enableHighAccuracy: true});
}
}
</script>
<script async defer src=\"https://maps.googleapis.com/maps/api/js?key=apiKey&callback=initMap\">
</script>
"][<|"Name"->name,"Latitude"->defaultPosition[[1,1]],"Longitude"->defaultPosition[[1,2]],"DefaultZoom"->defaultZoom,"apiKey"-> apiKey|>]]


Then we deploy a form and use the function as the control for one of the inputs.

CloudDeploy[FormFunction[{"location"-><|
"Label"->"Drag the map so the marker points at your location",
"Interpreter"->"StructuredGeoCoordinates",
"Control"->mapControl[apiKey,"location",Entity["City",{"Champaign","Illinois","UnitedStates"}]["Position"]]|>},
{#location,GeoGraphics[GeoMarker[#location],GeoRange->Quantity[1,"Miles"]]}&],
"https://www.wolframcloud.com/objects/3550411e-7493-4e1f-811e-8a1be25c1f38",
Permissions->"Public"]**strong text**


# The finished product

The resulting section of the form is intuitive and easy to use. It will point at the position given by GPS if the user gives permissions and the default position I set otherwise.

You can see for yourself and find out your exact geolocation here:

https://www.wolframcloud.com/objects/3550411e-7493-4e1f-811e-8a1be25c1f38

4 Replies
Sort By:
Posted 3 years ago
 @Christopher Wolfram @Carlo Barbieri Thank you guys again for making this possible. It has been serving me and the Korean birds well :)
Posted 3 years ago
 - Congratulations! This post is now a Staff Pick as distinguished by a badge on your profile! Thank you, keep it coming, and consider contributing your work to the The Notebook Archive! We added your image also to the top for leading above the fold graphics. You might want to consider using Permissions -> "Public" in CloudDeploy as currently the content at URL you has given at the end cannot be viewed by general public.
Posted 3 years ago
 Thank you for making this a staff pick and pointing out the permissions problem. I fixed it and improved the landing site for the FormFunction.
Posted 3 years ago