-
Notifications
You must be signed in to change notification settings - Fork 24
/
leaflet.magnifyingglass.js
159 lines (136 loc) · 4.52 KB
/
leaflet.magnifyingglass.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
L.MagnifyingGlass = L.Layer.extend({
options: {
radius: 100,
zoomOffset: 3,
layers: [ ],
fixedPosition: false,
latLng: [0, 0],
fixedZoom: -1
},
initialize: function(options) {
L.Util.setOptions(this, options);
this._fixedZoom = (this.options.fixedZoom != -1);
this._mainMap = null;
this._glassMap = null;
},
getMap: function(){
return this._glassMap;
},
_createMiniMap: function(elt) {
return new L.Map(elt, {
layers: this.options.layers,
zoom: this._getZoom(),
maxZoom: this._mainMap.getMaxZoom(),
minZoom: this._mainMap.getMinZoom(),
crs: this._mainMap.options.crs,
fadeAnimation: false,
// disable every controls and interaction means
attributionControl: false,
zoomControl: false,
boxZoom: false,
touchZoom: false,
scrollWheelZoom: false,
doubleClickZoom: false,
dragging: false,
keyboard: false,
});
},
_getZoom: function() {
return (this._fixedZoom) ?
this.options.fixedZoom :
this._mainMap.getZoom() + this.options.zoomOffset;
},
_updateZoom: function() {
this._glassMap.setZoom(this._getZoom());
},
setRadius: function(radius) {
this.options.radius = radius;
if(this._wrapperElt) {
this._wrapperElt.style.width = this.options.radius * 2 + 'px';
this._wrapperElt.style.height = this.options.radius * 2 + 'px';
}
},
setLatLng: function(latLng) {
this.options.latLng = latLng;
this._update(latLng);
},
_updateFromMouse: function(evt) {
this._update(evt.latlng, evt.layerPoint);
},
_updateFixed: function() {
this._update(this.options.latLng);
},
_update: function(latLng, layerPoint) {
// update mini map view, forcing no animation
this._glassMap.setView(latLng, this._getZoom(), {
pan : { animate: false }
});
// update the layer element position on the main map,
// using the one provided or reprojecting it
layerPoint = layerPoint || this._mainMap.latLngToLayerPoint(latLng);
this._wrapperElt.style.left = layerPoint.x - this.options.radius + 'px';
this._wrapperElt.style.top = layerPoint.y - this.options.radius + 'px';
},
/**
As defined by ILayer
*/
onAdd: function(map) {
this._mainMap = map;
// create a wrapper element and a container for the map inside it
this._wrapperElt = L.DomUtil.create('div', 'leaflet-magnifying-glass');
var glassMapElt = L.DomUtil.create('div', '', this._wrapperElt);
// Webkit border-radius clipping workaround (see CSS)
if(L.Browser.webkit)
L.DomUtil.addClass(glassMapElt, 'leaflet-magnifying-glass-webkit');
// build the map
this._glassMap = this._createMiniMap(glassMapElt);
// forward some DOM events as Leaflet events
L.DomEvent.addListener(this._wrapperElt, 'click', this._fireClick, this);
var opts = this.options;
this.setRadius(opts.radius);
this.setLatLng(opts.latLng);
this._glassMap.whenReady(function() {
if(opts.fixedPosition) {
this._mainMap.on('zoomend', this._updateFixed, this);
// for now, hide the elements during zoom transitions
L.DomUtil.addClass(this._wrapperElt, ('leaflet-zoom-hide'));
} else {
this._mainMap.on('mousemove', this._updateFromMouse, this);
if(!this._fixedZoom) {
this._mainMap.on('zoomend', this._updateZoom, this);
}
}
}, this);
// add the magnifying glass as a layer to the top-most pane
map.getPanes().popupPane.appendChild(this._wrapperElt);
// needed after the element has been added, otherwise tile loading is messy
this._glassMap.invalidateSize();
return this;
},
_fireClick: function(domMouseEvt) {
this.fire('click', domMouseEvt);
L.DomEvent.stopPropagation(domMouseEvt);
},
/**
As defined by ILayer
*/
onRemove: function(map) {
map.off('viewreset', this._updateFixed, this);
map.off('mousemove', this._updateFromMouse, this);
map.off('zoomend', this._updateZoom, this);
// layers must be explicitely removed before map destruction,
// otherwise they can't be reused if the mg is re-added
for(var i=0, l=this.options.layers.length; i<l; i++) {
this._glassMap.removeLayer(this.options.layers[i]);
}
this._glassMap.remove();
L.DomEvent.removeListener(this._wrapperElt, 'click', this._fireClick);
map.getPanes().popupPane.removeChild(this._wrapperElt);
this._mainMap = null;
return this;
}
});
L.magnifyingGlass = function (options) {
return new L.MagnifyingGlass(options);
};