+++ /dev/null
-/*
-Copyright (c) 2013 Dominik Moritz
-
-This file is part of the leaflet locate control. It is licensed under the MIT license.
-You can find the project at: https://github.com/domoritz/leaflet-locatecontrol
-*/
-L.Control.Locate = L.Control.extend({
- options: {
- position: 'topleft',
- drawCircle: true,
- follow: false, // follow with zoom and pan the user's location
- stopFollowingOnDrag: false, // if follow is true, stop following when map is dragged
- // range circle
- circleStyle: {
- color: '#136AEC',
- fillColor: '#136AEC',
- fillOpacity: 0.15,
- weight: 2,
- opacity: 0.5
- },
- // inner marker
- markerStyle: {
- color: '#136AEC',
- fillColor: '#2A93EE',
- fillOpacity: 0.7,
- weight: 2,
- opacity: 0.9,
- radius: 5
- },
- // changes to range circle and inner marker while following
- // it is only necessary to provide the things that should change
- followCircleStyle: {},
- followMarkerStyle: {
- //color: '#FFA500',
- //fillColor: '#FFB000'
- },
- metric: true,
- onLocationError: function(err) {
- // this event is called in case of any location error
- // that is not a time out error.
- alert(err.message);
- },
- onLocationOutsideMapBounds: function(context) {
- // this event is repeatedly called when the location changes
- alert(context.options.strings.outsideMapBoundsMsg);
- },
- setView: true, // automatically sets the map view to the user's location
- strings: {
- title: "Show me where I am",
- popup: "You are within {distance} {unit} from this point",
- outsideMapBoundsMsg: "You seem located outside the boundaries of the map"
- },
- locateOptions: {}
- },
-
- onAdd: function (map) {
- var container = L.DomUtil.create('div',
- 'leaflet-control-locate leaflet-bar leaflet-control');
-
- var self = this;
- this._layer = new L.LayerGroup();
- this._layer.addTo(map);
- this._event = undefined;
-
- this._locateOptions = {
- watch: true // if you overwrite this, visualization cannot be updated
- };
- L.extend(this._locateOptions, this.options.locateOptions);
- L.extend(this._locateOptions, {
- setView: false // have to set this to false because we have to
- // do setView manually
- });
-
- // extend the follow marker style and circle from the normal style
- var tmp = {};
- L.extend(tmp, this.options.markerStyle, this.options.followMarkerStyle);
- this.options.followMarkerStyle = tmp;
- tmp = {};
- L.extend(tmp, this.options.circleStyle, this.options.followCircleStyle);
- this.options.followCircleStyle = tmp;
-
- var link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', container);
- link.href = '#';
- link.title = this.options.strings.title;
-
- L.DomEvent
- .on(link, 'click', L.DomEvent.stopPropagation)
- .on(link, 'click', L.DomEvent.preventDefault)
- .on(link, 'click', function() {
- if (self._active && (map.getBounds().contains(self._event.latlng) || !self.options.setView ||
- isOutsideMapBounds())) {
- stopLocate();
- } else {
- if (self.options.setView) {
- self._locateOnNextLocationFound = true;
- }
- if(!self._active) {
- map.locate(self._locateOptions);
- }
- self._active = true;
- if (self.options.follow) {
- startFollowing();
- }
- if (!self._event) {
- L.DomUtil.addClass(self._container, "requesting");
- L.DomUtil.removeClass(self._container, "active");
- L.DomUtil.removeClass(self._container, "following");
- } else {
- visualizeLocation();
- }
- }
- })
- .on(link, 'dblclick', L.DomEvent.stopPropagation);
-
- var onLocationFound = function (e) {
- // no need to do anything if the location has not changed
- if (self._event &&
- (self._event.latlng.lat == e.latlng.lat &&
- self._event.latlng.lng == e.latlng.lng)) {
- return;
- }
-
- if (!self._active) {
- return;
- }
-
- self._event = e;
-
- if (self.options.follow && self._following) {
- self._locateOnNextLocationFound = true;
- }
-
- visualizeLocation();
- };
-
- var startFollowing = function() {
- self._following = true;
- if (self.options.stopFollowingOnDrag) {
- map.on('dragstart', stopFollowing);
- }
- };
-
- var stopFollowing = function() {
- self._following = false;
- if (self.options.stopFollowingOnDrag) {
- map.off('dragstart', stopFollowing);
- }
- visualizeLocation();
- };
-
- var isOutsideMapBounds = function () {
- if (self._event === undefined)
- return false;
- return map.options.maxBounds &&
- !map.options.maxBounds.contains(self._event.latlng);
- };
-
- var visualizeLocation = function() {
- if (self._event.accuracy === undefined)
- self._event.accuracy = 0;
-
- var radius = self._event.accuracy;
- if (self._locateOnNextLocationFound) {
- if (isOutsideMapBounds()) {
- self.options.onLocationOutsideMapBounds(self);
- } else {
- map.fitBounds(self._event.bounds);
- }
- self._locateOnNextLocationFound = false;
- }
-
- // circle with the radius of the location's accuracy
- var style;
- if (self.options.drawCircle) {
- if (self._following) {
- style = self.options.followCircleStyle;
- } else {
- style = self.options.circleStyle;
- }
-
- if (!self._circle) {
- self._circle = L.circle(self._event.latlng, radius, style)
- .addTo(self._layer);
- } else {
- self._circle.setLatLng(self._event.latlng).setRadius(radius);
- }
- }
-
- var distance, unit;
- if (self.options.metric) {
- distance = radius.toFixed(0);
- unit = "meters";
- } else {
- distance = (radius * 3.2808399).toFixed(0);
- unit = "feet";
- }
-
- // small inner marker
- var m;
- if (self._following) {
- m = self.options.followMarkerStyle;
- } else {
- m = self.options.markerStyle;
- }
-
- var t = self.options.strings.popup;
- if (!self._circleMarker) {
- self._circleMarker = L.circleMarker(self._event.latlng, m)
- .bindPopup(L.Util.template(t, {distance: distance, unit: unit}))
- .addTo(self._layer);
- } else {
- self._circleMarker.setLatLng(self._event.latlng)
- .bindPopup(L.Util.template(t, {distance: distance, unit: unit}))
- ._popup.setLatLng(self._event.latlng);
- }
-
- if (!self._container)
- return;
- if (self._following) {
- L.DomUtil.removeClass(self._container, "requesting");
- L.DomUtil.addClass(self._container, "active");
- L.DomUtil.addClass(self._container, "following");
- } else {
- L.DomUtil.removeClass(self._container, "requesting");
- L.DomUtil.addClass(self._container, "active");
- L.DomUtil.removeClass(self._container, "following");
- }
- };
-
- var resetVariables = function() {
- self._active = false;
- self._locateOnNextLocationFound = self.options.setView;
- self._following = false;
- };
-
- resetVariables();
-
- var stopLocate = function() {
- map.stopLocate();
- map.off('dragstart', stopFollowing);
-
- L.DomUtil.removeClass(self._container, "requesting");
- L.DomUtil.removeClass(self._container, "active");
- L.DomUtil.removeClass(self._container, "following");
- resetVariables();
-
- self._layer.clearLayers();
- self._circleMarker = undefined;
- self._circle = undefined;
- };
-
- var onLocationError = function (err) {
- // ignore time out error if the location is watched
- if (err.code == 3 && this._locateOptions.watch) {
- return;
- }
-
- stopLocate();
- self.options.onLocationError(err);
- };
-
- // event hooks
- map.on('locationfound', onLocationFound, self);
- map.on('locationerror', onLocationError, self);
-
- return container;
- }
-});
-
-L.Map.addInitHook(function () {
- if (this.options.locateControl) {
- this.locateControl = L.control.locate();
- this.addControl(this.locateControl);
- }
-});
-
-L.control.locate = function (options) {
- return new L.Control.Locate(options);
-};