c919618ea0bf80decb4954143299c567dcc66398
[lhc/web/www.git] / www / plugins / gis / lib / leaflet / plugins / Google.js
1 /*
2 * Google layer using Google Maps API
3 */
4
5 /* global google: true */
6
7 L.Google = L.Class.extend({
8 includes: L.Mixin.Events,
9
10 options: {
11 minZoom: 0,
12 maxZoom: 18,
13 tileSize: 256,
14 subdomains: 'abc',
15 errorTileUrl: '',
16 attribution: '',
17 opacity: 1,
18 continuousWorld: false,
19 noWrap: false,
20 mapOptions: {
21 backgroundColor: '#dddddd'
22 }
23 },
24
25 // Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN
26 initialize: function(type, options) {
27 L.Util.setOptions(this, options);
28
29 this._ready = google.maps.Map !== undefined;
30 if (!this._ready) L.Google.asyncWait.push(this);
31
32 this._type = type || 'SATELLITE';
33 },
34
35 onAdd: function(map, insertAtTheBottom) {
36 this._map = map;
37 this._insertAtTheBottom = insertAtTheBottom;
38
39 // create a container div for tiles
40 this._initContainer();
41 this._initMapObject();
42
43 // set up events
44 map.on('viewreset', this._resetCallback, this);
45
46 this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
47 map.on('move', this._update, this);
48
49 map.on('zoomanim', this._handleZoomAnim, this);
50
51 //20px instead of 1em to avoid a slight overlap with google's attribution
52 map._controlCorners.bottomright.style.marginBottom = '20px';
53
54 this._reset();
55 this._update();
56 },
57
58 onRemove: function(map) {
59 map._container.removeChild(this._container);
60
61 map.off('viewreset', this._resetCallback, this);
62
63 map.off('move', this._update, this);
64
65 map.off('zoomanim', this._handleZoomAnim, this);
66
67 map._controlCorners.bottomright.style.marginBottom = '0em';
68 },
69
70 getAttribution: function() {
71 return this.options.attribution;
72 },
73
74 setOpacity: function(opacity) {
75 this.options.opacity = opacity;
76 if (opacity < 1) {
77 L.DomUtil.setOpacity(this._container, opacity);
78 }
79 },
80
81 setElementSize: function(e, size) {
82 e.style.width = size.x + 'px';
83 e.style.height = size.y + 'px';
84 },
85
86 _initContainer: function() {
87 var tilePane = this._map._container,
88 first = tilePane.firstChild;
89
90 if (!this._container) {
91 this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left');
92 this._container.id = '_GMapContainer_' + L.Util.stamp(this);
93 this._container.style.zIndex = 'auto';
94 }
95
96 tilePane.insertBefore(this._container, first);
97
98 this.setOpacity(this.options.opacity);
99 this.setElementSize(this._container, this._map.getSize());
100 },
101
102 _initMapObject: function() {
103 if (!this._ready) return;
104 this._google_center = new google.maps.LatLng(0, 0);
105 var map = new google.maps.Map(this._container, {
106 center: this._google_center,
107 zoom: 0,
108 tilt: 0,
109 mapTypeId: google.maps.MapTypeId[this._type],
110 disableDefaultUI: true,
111 keyboardShortcuts: false,
112 draggable: false,
113 disableDoubleClickZoom: true,
114 scrollwheel: false,
115 streetViewControl: false,
116 styles: this.options.mapOptions.styles,
117 backgroundColor: this.options.mapOptions.backgroundColor
118 });
119
120 var _this = this;
121 this._reposition = google.maps.event.addListenerOnce(map, 'center_changed',
122 function() { _this.onReposition(); });
123 this._google = map;
124
125 google.maps.event.addListenerOnce(map, 'idle',
126 function() { _this._checkZoomLevels(); });
127 google.maps.event.addListenerOnce(map, 'tilesloaded',
128 function() { _this.fire('load'); });
129 //Reporting that map-object was initialized.
130 this.fire('MapObjectInitialized', { mapObject: map });
131 },
132
133 _checkZoomLevels: function() {
134 //setting the zoom level on the Google map may result in a different zoom level than the one requested
135 //(it won't go beyond the level for which they have data).
136 // verify and make sure the zoom levels on both Leaflet and Google maps are consistent
137 if (this._google.getZoom() !== this._map.getZoom()) {
138 //zoom levels are out of sync. Set the leaflet zoom level to match the google one
139 this._map.setZoom( this._google.getZoom() );
140 }
141 },
142
143 _resetCallback: function(e) {
144 this._reset(e.hard);
145 },
146
147 _reset: function(clearOldContainer) {
148 this._initContainer();
149 },
150
151 _update: function(e) {
152 if (!this._google) return;
153 this._resize();
154
155 var center = this._map.getCenter();
156 var _center = new google.maps.LatLng(center.lat, center.lng);
157
158 this._google.setCenter(_center);
159 this._google.setZoom(Math.round(this._map.getZoom()));
160
161 this._checkZoomLevels();
162 },
163
164 _resize: function() {
165 var size = this._map.getSize();
166 if (this._container.style.width === size.x &&
167 this._container.style.height === size.y)
168 return;
169 this.setElementSize(this._container, size);
170 this.onReposition();
171 },
172
173
174 _handleZoomAnim: function (e) {
175 var center = e.center;
176 var _center = new google.maps.LatLng(center.lat, center.lng);
177
178 this._google.setCenter(_center);
179 this._google.setZoom(Math.round(e.zoom));
180 },
181
182
183 onReposition: function() {
184 if (!this._google) return;
185 google.maps.event.trigger(this._google, 'resize');
186 }
187 });
188
189 L.Google.asyncWait = [];
190 L.Google.asyncInitialize = function() {
191 var i;
192 for (i = 0; i < L.Google.asyncWait.length; i++) {
193 var o = L.Google.asyncWait[i];
194 o._ready = true;
195 if (o._container) {
196 o._initMapObject();
197 o._update();
198 }
199 }
200 L.Google.asyncWait = [];
201 };