Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2504 - 1
L.Control.Locate = L.Control.extend({
2
    options: {
3
        position: 'topleft',
4
        drawCircle: true,
5
        follow: false,  // follow with zoom and pan the user's location
6
        // range circle
7
        circleStyle: {
8
                color: '#136AEC',
9
                fillColor: '#136AEC',
10
                fillOpacity: 0.15,
11
                weight: 2,
12
                opacity: 0.5
13
            },
14
        // inner marker
15
        markerStyle: {
16
            color: '#136AEC',
17
            fillColor: '#2A93EE',
18
            fillOpacity: 0.7,
19
            weight: 2,
20
            opacity: 0.9,
21
            radius: 4
22
        },
23
        metric: true,
24
        debug: false,
25
        onLocationError: function(err) {
26
            alert(err.message);
27
        },
28
        title: "Show me where I am",
29
        popupText: ["You are within ", " from this point"],
30
        setView: true, // automatically sets the map view to the user's location
31
        locateOptions: {}
32
    },
33
 
34
    onAdd: function (map) {
35
        var className = 'leaflet-control-locate',
36
            classNames = className + ' leaflet-control-zoom leaflet-bar leaflet-control',
37
            container = L.DomUtil.create('div', classNames);
38
 
39
        var self = this;
40
        this._layer = new L.LayerGroup();
41
        this._layer.addTo(map);
42
        this._event = undefined;
43
        // nested extend so that the first can overwrite the second
44
        // and the second can overwrite the third
45
        this._locateOptions = L.extend(L.extend({
46
            'setView': false // have to set this to false because we have to
47
                             // do setView manually
48
        }, this.options.locateOptions), {
49
            'watch': true  // if you overwrite this, visualization cannot be updated
50
        });
51
 
52
        var link = L.DomUtil.create('a', 'leaflet-bar-part leaflet-bar-part-single', container);
53
        link.href = '#';
54
        link.title = this.options.title;
55
 
56
        var _log = function(data) {
57
            if (self.options.debug) {
58
                console.log(data);
59
            }
60
        };
61
 
62
        L.DomEvent
63
            .on(link, 'click', L.DomEvent.stopPropagation)
64
            .on(link, 'click', L.DomEvent.preventDefault)
65
            .on(link, 'click', function() {
66
                if (self._active && (map.getBounds().contains(self._event.latlng) || !self.options.setView)) {
67
                    stopLocate();
68
                } else {
69
                    if (self.options.setView) {
70
                        self._locateOnNextLocationFound = true;
71
                    }
72
                    if(!self._active) {
73
                        map.locate(self._locateOptions);
74
                    }
75
                    self._active = true;
76
                    if (!self._event) {
77
                        self._container.className = classNames + " requesting";
78
                    } else {
79
                        visualizeLocation();
80
                    }
81
                }
82
            })
83
            .on(link, 'dblclick', L.DomEvent.stopPropagation);
84
 
85
        var onLocationFound = function (e) {
86
            _log('onLocationFound');
87
 
88
            self._active = true;
89
 
90
            if (self._event &&
91
                (self._event.latlng.lat != e.latlng.lat ||
92
                 self._event.latlng.lng != e.latlng.lng)) {
93
                _log('location has changed');
94
            }
95
 
96
            self._event = e;
97
 
98
            if (self.options.follow) {
99
                self._locateOnNextLocationFound = true;
100
            }
101
 
102
            visualizeLocation();
103
        };
104
 
105
        var visualizeLocation = function() {
106
            _log('visualizeLocation,' + 'setView:' + self._locateOnNextLocationFound);
107
 
108
            var radius = self._event.accuracy / 2;
109
 
110
            if (self._locateOnNextLocationFound) {
111
                map.fitBounds(self._event.bounds);
112
                self._locateOnNextLocationFound = false;
113
            }
114
 
115
            self._layer.clearLayers();
116
 
117
            // circle with the radius of the location's accuracy
118
            if (self.options.drawCircle) {
119
                L.circle(self._event.latlng, radius, self.options.circleStyle)
120
                    .addTo(self._layer);
121
            }
122
 
123
            var distance, unit;
124
            if (self.options.metric) {
125
                distance = radius.toFixed(0);
126
                unit = "meters";
127
            } else {
128
                distance = (radius * 3.2808399).toFixed(0);
129
                unit = "feet";
130
            }
131
 
132
            // small inner marker
133
            var t = self.options.popupText;
134
            L.circleMarker(self._event.latlng, self.options.markerStyle)
135
                .bindPopup(t[0] + distance + " " + unit  + t[1])
136
                .addTo(self._layer);
137
 
138
            if (!self._container)
139
                return;
140
            self._container.className = classNames + " active";
141
        };
142
 
143
        var resetVariables = function() {
144
            self._active = false;
145
            self._locateOnNextLocationFound = true;
146
        };
147
 
148
        resetVariables();
149
 
150
        var stopLocate = function() {
151
            _log('stopLocate');
152
            map.stopLocate();
153
 
154
            self._container.className = classNames;
155
            resetVariables();
156
 
157
            self._layer.clearLayers();
158
        };
159
 
160
 
161
        var onLocationError = function (err) {
162
            _log('onLocationError');
163
 
164
            // ignore timeout error if the location is watched
165
            if (err.code==3 && this._locateOptions.watch) {
166
                return;
167
            }
168
 
169
            stopLocate();
170
            self.options.onLocationError(err);
171
        };
172
 
173
        // event hooks
174
        map.on('locationfound', onLocationFound, self);
175
        map.on('locationerror', onLocationError, self);
176
 
177
        return container;
178
    }
179
});
180
 
181
L.Map.addInitHook(function () {
182
    if (this.options.locateControl) {
183
        this.locateControl = L.control.locate();
184
        this.addControl(this.locateControl);
185
    }
186
});
187
 
188
L.control.locate = function (options) {
189
    return new L.Control.Locate(options);
190
};