+ var icon = this._getIconSVG(opt, style);
+
+ this._locationIcon = L.divIcon({
+ className: icon.className,
+ html: icon.svg,
+ iconSize: [icon.w,icon.h],
+ });
+
+ this.setIcon(this._locationIcon);
+ },
+
+ /**
+ * Return the raw svg for the shape
+ *
+ * Split so can be easily overridden
+ */
+ _getIconSVG: function(options, style) {
+ var r = options.radius;
+ var w = options.weight;
+ var s = r + w;
+ var s2 = s * 2;
+ var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="'+s2+'" height="'+s2+'" version="1.1" viewBox="-'+s+' -'+s+' '+s2+' '+s2+'">' +
+ '<circle r="'+r+'" style="'+style+'" />' +
+ '</svg>';
+ return {
+ className: 'leafet-control-locate-location',
+ svg: svg,
+ w: s2,
+ h: s2
+ };
+ },
+
+ setStyle: function(style) {
+ L.Util.setOptions(this, style);
+ this.createIcon();
+ }
+ });
+
+ var CompassMarker = LocationMarker.extend({
+ initialize: function (latlng, heading, options) {
+ L.Util.setOptions(this, options);
+ this._latlng = latlng;
+ this._heading = heading;
+ this.createIcon();
+ },
+
+ setHeading: function(heading) {
+ this._heading = heading;
+ },
+
+ /**
+ * Create a styled arrow compass marker
+ */
+ _getIconSVG: function(options, style) {
+ var r = options.radius;
+ var w = (options.width + options.weight);
+ var h = (r+options.depth + options.weight)*2;
+ var path = 'M0,0 l'+(options.width/2)+','+options.depth+' l-'+(w)+',0 z';
+ var svgstyle = 'transform: rotate('+this._heading+'deg)';
+ var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="'+(w)+'" height="'+h+'" version="1.1" viewBox="-'+(w/2)+' 0 '+w+' '+h+'" style="'+svgstyle+'">'+
+ '<path d="'+path+'" style="'+style+'" />'+
+ '</svg>';
+ return {
+ className: 'leafet-control-locate-heading',
+ svg: svg,
+ w: w,
+ h: h
+ };
+ },
+ });
+
+
+ var LocateControl = L.Control.extend({
+ options: {
+ /** Position of the control */
+ position: 'topleft',
+ /** The layer that the user's location should be drawn on. By default creates a new layer. */
+ layer: undefined,
+ /**
+ * Automatically sets the map view (zoom and pan) to the user's location as it updates.
+ * While the map is following the user's location, the control is in the `following` state,
+ * which changes the style of the control and the circle marker.
+ *
+ * Possible values:
+ * - false: never updates the map view when location changes.
+ * - 'once': set the view when the location is first determined
+ * - 'always': always updates the map view when location changes.
+ * The map view follows the user's location.
+ * - 'untilPan': like 'always', except stops updating the
+ * view if the user has manually panned the map.
+ * The map view follows the user's location until she pans.
+ * - 'untilPanOrZoom': (default) like 'always', except stops updating the
+ * view if the user has manually panned the map.
+ * The map view follows the user's location until she pans.
+ */
+ setView: 'untilPanOrZoom',
+ /** Keep the current map zoom level when setting the view and only pan. */
+ keepCurrentZoomLevel: false,
+ /** Smooth pan and zoom to the location of the marker. Only works in Leaflet 1.0+. */
+ flyTo: false,
+ /**
+ * The user location can be inside and outside the current view when the user clicks on the
+ * control that is already active. Both cases can be configures separately.
+ * Possible values are:
+ * - 'setView': zoom and pan to the current location
+ * - 'stop': stop locating and remove the location marker
+ */
+ clickBehavior: {
+ /** What should happen if the user clicks on the control while the location is within the current view. */
+ inView: 'stop',
+ /** What should happen if the user clicks on the control while the location is outside the current view. */
+ outOfView: 'setView',
+ },
+ /**
+ * If set, save the map bounds just before centering to the user's
+ * location. When control is disabled, set the view back to the
+ * bounds that were saved.
+ */
+ returnToPrevBounds: false,
+ /**
+ * Keep a cache of the location after the user deactivates the control. If set to false, the user has to wait
+ * until the locate API returns a new location before they see where they are again.
+ */
+ cacheLocation: true,
+ /** If set, a circle that shows the location accuracy is drawn. */
+ drawCircle: true,
+ /** If set, the marker at the users' location is drawn. */
+ drawMarker: true,
+ /** If set and supported then show the compass heading */
+ showCompass: true,
+ /** The class to be used to create the marker. For example L.CircleMarker or L.Marker */
+ markerClass: LocationMarker,
+ /** The class us be used to create the compass bearing arrow */
+ compassClass: CompassMarker,
+ /** Accuracy circle style properties. NOTE these styles should match the css animations styles */
+ circleStyle: {
+ className: 'leaflet-control-locate-circle',
+ color: '#136AEC',
+ fillColor: '#136AEC',
+ fillOpacity: 0.15,
+ weight: 0
+ },
+ /** Inner marker style properties. Only works if your marker class supports `setStyle`. */
+ markerStyle: {
+ className: 'leaflet-control-locate-marker',
+ color: '#fff',
+ fillColor: '#2A93EE',
+ fillOpacity: 1,
+ weight: 3,
+ opacity: 1,
+ radius: 9
+ },
+ /** Compass */
+ compassStyle: {
+ fillColor: '#2A93EE',
+ fillOpacity: 1,
+ weight: 0,
+ color: '#fff',
+ opacity: 1,
+ radius: 9, // How far is the arrow is from the center of of the marker
+ width: 9, // Width of the arrow
+ depth: 6 // Length of the arrow
+ },
+ /**
+ * Changes to accuracy circle and inner marker while following.
+ * It is only necessary to provide the properties that should change.
+ */
+ followCircleStyle: {},
+ followMarkerStyle: {
+ // color: '#FFA500',
+ // fillColor: '#FFB000'
+ },
+ followCompassStyle: {},
+ /** The CSS class for the icon. For example fa-location-arrow or fa-map-marker */
+ icon: 'fa fa-map-marker',
+ iconLoading: 'fa fa-spinner fa-spin',
+ /** The element to be created for icons. For example span or i */
+ iconElementTag: 'span',
+ /** Padding around the accuracy circle. */
+ circlePadding: [0, 0],
+ /** Use metric units. */
+ metric: true,
+ /**
+ * This callback can be used in case you would like to override button creation behavior.
+ * This is useful for DOM manipulation frameworks such as angular etc.
+ * This function should return an object with HtmlElement for the button (link property) and the icon (icon property).
+ */
+ createButtonCallback: function (container, options) {
+ var link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', container);
+ link.title = options.strings.title;
+ var icon = L.DomUtil.create(options.iconElementTag, options.icon, link);
+ return { link: link, icon: icon };
+ },
+ /** This event is called in case of any location error that is not a time out error. */
+ onLocationError: function(err, control) {
+ alert(err.message);
+ },
+ /**
+ * This event is called when the user's location is outside the bounds set on the map.
+ * The event is called repeatedly when the location changes.
+ */
+ onLocationOutsideMapBounds: function(control) {
+ control.stop();
+ alert(control.options.strings.outsideMapBoundsMsg);
+ },
+ /** Display a pop-up when the user click on the inner marker. */
+ showPopup: true,
+ strings: {
+ title: "Show me where I am",
+ metersUnit: "meters",
+ feetUnit: "feet",
+ popup: "You are within {distance} {unit} from this point",
+ outsideMapBoundsMsg: "You seem located outside the boundaries of the map"
+ },
+ /** The default options passed to leaflets locate method. */
+ locateOptions: {
+ maxZoom: Infinity,
+ watch: true, // if you overwrite this, visualization cannot be updated
+ setView: false // have to set this to false because we have to
+ // do setView manually