<!DOCTYPE html>
<html>
<head>
<link href="//js.arcgis.com/3.13/esri/css/esri.css" rel="stylesheet" data-semver="3.13.0" data-require="arcgis@3.13.0" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div id="map">
<div id="locationButtons">
<div id="homeButton"></div>
<button type="button" title="Geolocate" class="geolocate" id="geolocateButton"></button>
</div>
</div>
<script>
(function() {
var root = location.pathname.replace(/\/[^\/]*$/, "");
var dojoConfig = {
async: true,
packages: [{
name: "geolocate-button",
location: root,
main: "geolocate-button"
}]
};
window.dojoConfig = dojoConfig;
}());
</script>
<script src="//js.arcgis.com/3.13/" data-semver="3.13.0" data-require="arcgis@3.13.0"></script>
<script src="script.js"></script>
</body>
</html>
require(["esri/map", "geolocate-button"], function(Map, createGeolocateButton) {
var map;
map = new Map("map", {
basemap: "hybrid",
center: [-120.80566406246835, 47.41322033015946],
zoom: 7,
showAttribution: true
});
createGeolocateButton(document.getElementById("geolocateButton"), map);
});
html, body, #map, .map.container {
padding:0;
margin:0;
height:100%;
}
#locationButtons {
position: absolute;
top: 95px;
left: 20px;
z-index: 1;
}
button.geolocate {
width: 34px;
height: 34px;
border: none;
border-radius: 5px;
background-position: center center;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaBAMAAABbZFH9AAAAIVBMVEX////////09PT19fX09PTz8/Pz8/P09PT09PT09PT09PQZGjmlAAAAC3RSTlMABC00W2mAn9DS6Vd3VDgAAABmSURBVHhetZA7DoAgEEQXPzF2Jl7A2kpvYElpwxW2tuMCNHSW1p7UjaCbuLEiTDHDS8gMAYIwRDL9qjczQ+HtMbw0LlCdDyhHprtI5U7WTnc3Yr1RNiudPsQ3RQsvyHV+mVSOf7kAHRkVQU75GE0AAAAASUVORK5CYII=') /*../images/geolocate.png*/;
background-repeat: no-repeat;
background-color: #666;
background-color: rgba(102,102,102,0.80);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
margin-top: 0.2em;
cursor: pointer;
}
button.geolocate.busy {
background-image: url('data:image/gif;base64,R0lGODlhEAAQAPMPAJzNwxSJceDv7L7e13q8rwCAZlirmjaahorEuPD39SSRe2izpEaij6zVzASBaP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAPACwAAAAAEAAQAAAEcfDJl+gydeonlEhFIVCbJBRK4ojJqAkjUiArnEkJM4OOYXymjEDnGLhwQFyicTjiNAiGD1CiJK5RBoNaul6tA8ItqEkgAgxnyzghKABmBEzQoLA5I8Fh0AAI5E8TCQYEDwBUAnAlAgQjhxIDYyUDA1URACH5BAUKAA8ALAAAAAAPABAAAARd8Mn5yJKJTiaVFEGjSUeiOIJSDKMEKAFQcJMRJ8FhFUWWSYbCQTAZEFu01qOxIBBYygfAsFhAox/A6DdpMAxbwQ/BaCQADYH6KNYsBAPzVUPQxiVzDCBzfxyVaiMRACH5BAUKAA8ALAAAAAAQAA8AAARa8Mn5AKJYLslUSkcmOUbSJYaYVEXTNZMwSMTRgAyCHIWAFD1NIBUDAAuzyWCxUhYukoEOIMh8rg2CVsR9wLqUBaLZBRAGiQH6qpIgBPCEgIwBzOAPOfeLz1MiACH5BAUKAA8ALAAAAAAQABAAAARc8MkpAb2SpGeYNAP2HATnLdgmBUMXookgIYvMEADgJVagEqSH6jFQiB4liqyW2AAaDdEiEHCAcgDZZVHoHiihi2AsUAkQluNkkH2M1UJJYtAcHgeyJtwtt8P1GBEAIfkEBQoACAAsAAAAABAADgAABEUQyYkIoVgaWQrP3NYhASgRXgeQmBEMSHFYXhVPRrFh9UrtmMNEgAD4gp1CyXLJlD5DzECWOU6mHSJCa0pmuJQBUAIGRQAAIfkEBQoADgAsAAAAABAAEAAABGvQyenGoNilJhGRhJAlBIcgDqKImbAIpxCg1NCICGARR6UwksQAMUhMEgKD48CSCDiUBANg1AiuVQrAYGAgrtgMQKEILKIYwQGAQTYdTwkwKDAmqoFC0hHIZhoFSg5QaBMKBRcjaQVsGY5+EQAh+QQFCgAPACwAAAAAEAAQAAAEW/DJ+YSgWA4JAM/c1XgAA0pIMj5Mg1nJ0wwWsEjMLQl0tgQGTOKCWbgmiSSosVgEk8pMg3E4EE4TQyOK3TwWMRBhoXgkbodToIB4XHmgxJpIjDsKF8cxbjiEKREAIfkEBQoADgAsAQABAA8ADwAABFbQSSHHkE3qWu9Y2+Zdy+UkpyZQTkM4goFIiYCGxPFu94aYoeCAQMwENR+D7EgrBWusmsKx2xQKCARjOmP4CgSFAuCYhQRXSiBxODYKl8DaoQCqNIZjBAAh+QQFCgAPACwAAAAAEAAQAAAEXfDJ+VKiWN4nhBwbJlwdB4RU4nUJ4mGbZQ2NhAAZDCx4jgEvH0WAKAonAoKy9lEMMK4ho1DoTRgBhMZROHgUgMaC8QAoFhLA03Y41HrBiSLRfhgcPsf3ICHnNko5EQAh+QQFCgAOACwAAAEAEAAPAAAEWtDJ6VKSgmpp5dha922ZJpTACE4NMlxUSanOEtwL2OzDUfwMEADgSpwAAZkEsHK8JonFgSlR1BIKRsOBMDgNBElDBjAwBoEtTHNwmB2E9mZgdTCCNeUGgQBFAAAh+QQFCgAPACwAAAEAEAAPAAAEWPDJSV+qeCZRBcfCRRUFUonJ8A1k8U2CWhFF04mSomfP4AsGRyBAyPgan0SDgbFVDJKXBLFwPg6PIsPgAywkBIBkIBE3CAsBlhdgoh8AJki+gCaKvLIYEwEAIfkEBQoADwAsAAABAA8ADwAABFrwyRGEvPiOorKXRtF8UvcIReEJyWkC45WwGOAMWSshB8MgnplAQFAYgbmhpTUweHAywiPgaSCgTuCCMGwATrDTJDBASBeWh059WDzMjwZhfXG/pY8vKR7DRAAAOw==') /*../images/ajax-loader.gif*/;
pointer-events: none;
cursor: default;
}
button.geolocate:hover {
background-color: #333;
background-color: rgba(102,102,102,0.90);
}
button.geolocate:active {
background-color: #ccc;
background-color: rgba(102,102,102,0.60);
}
ArcGIS JavaScript API: Geolocate Button
=======================================
Creates a Geolocate Button. When the user clicks the button, a popup will appear in the user's current location.
* Displays accuracy in meters or km.
/*global define*/
define([
"esri/graphic",
"esri/InfoTemplate",
"esri/geometry/Point",
"esri/geometry/Circle",
"esri/geometry/webMercatorUtils"
], function (Graphic, InfoTemplate, Point, Circle, webMercatorUtils) {
/**
* Creates a geolocate button.
* @param {HTMLButtonElement} button
* @param {esri/Map} map
*/
function createGeolocateButton(button, map) {
var infoTemplate, nFormat;
// Setup NumberFormat object if the browser supports it.
nFormat = (window.Intl && window.Intl.NumberFormat) ? new window.Intl.NumberFormat() : null;
/**
* Formats an amount in meters.
* @param {number} m - A number of meters.
* @returns {string}
*/
function formatMeters(m) {
var value, unit;
value = m;
unit = "meters";
if (m > 1000) {
value = m / 1000;
unit = "km.";
}
if (nFormat) { // Make sure browser implements Intl.NumberFormat
value = nFormat.format(value);
}
return [value, unit].join(" ");
}
/**
* Shows an info window at the given position.
* Displays a Circle on the map showing the position accuracy.
* @param {external:Position} position
*/
function showLocationPopup(position) {
var pt, attributes, accuracy, circle;
button.classList.remove("busy");
accuracy = position.coords.accuracy; // In meters.
pt = new Point(position.coords.longitude, position.coords.latitude);
pt = webMercatorUtils.geographicToWebMercator(pt);
circle = new Circle(pt, {
radius: accuracy, // Default unit is already meters.
geodesic: true
});
attributes = {
lat: position.coords.latitude.toFixed(6),
long: position.coords.longitude.toFixed(6),
accuracy: formatMeters(accuracy)
};
if (map.infoWindow.setFeatures) {
map.infoWindow.setFeatures([
new Graphic(circle, null, attributes, infoTemplate)
]);
map.infoWindow.show(map.toScreen(pt));
} else {
map.infoWindow.setTitle("You are here").setContent(
["Lat: ", attributes.lat, "<br /> Long:", attributes.long].join()
).show(map.toScreen(pt));
}
map.setExtent(circle.getExtent(), false);
}
/**
* Shows an error alert message
* @param {external:PositionError} error
*/
function showLocateError(error) {
var message = "", strErrorCode;
button.classList.remove("busy");
// Check for known errors
switch (error.code) {
case error.PERMISSION_DENIED:
message = "This website does not have permission to use the Geolocation API";
break;
case error.POSITION_UNAVAILABLE:
message = "The current position could not be determined.";
break;
case error.PERMISSION_DENIED_TIMEOUT:
message = "The current position could not be determined within the specified timeout period.";
break;
}
// If it's an unknown error, build a message that includes
// information that helps identify the situation so that
// the error handler can be updated.
if (message === "") {
strErrorCode = error.code.toString();
message = "The position could not be determined due to an unknown error (Code: " + strErrorCode + ").";
}
alert(message);
}
/**
* Calls the navigator.geolocation.getCurrentPosition function.
*/
function geolocate() {
button.classList.add("busy");
navigator.geolocation.getCurrentPosition(showLocationPopup, showLocateError, {
maximumAge: 0,
timeout: 30000,
enableHighAccuracy: true
});
}
// This info template is used to format the geocode results in the info window.
infoTemplate = new InfoTemplate(
"You are here", [
"<dl>",
"<dt>Latitude</dt><dd>${lat}</dd>",
"<dt>Longitude</dt><dd>${long}</dd>",
"<dt>Accuracy</dt><dd>±${accuracy}</dd>",
"</dl>"].join("")
);
// If the browser supports geolocation, setup the button.
// Otherwise, remove the button.
if (navigator.geolocation) {
button.onclick = geolocate;
} else {
button.disabled = true;
}
}
return createGeolocateButton;
});