Showing
2 changed files
with
394 additions
and
1 deletions
@@ -18,6 +18,7 @@ import tinycolor from 'tinycolor2'; | @@ -18,6 +18,7 @@ import tinycolor from 'tinycolor2'; | ||
18 | import TbGoogleMap from './google-map'; | 18 | import TbGoogleMap from './google-map'; |
19 | import TbOpenStreetMap from './openstreet-map'; | 19 | import TbOpenStreetMap from './openstreet-map'; |
20 | import TbImageMap from './image-map'; | 20 | import TbImageMap from './image-map'; |
21 | +import TbTencentMap from './tencent-map'; | ||
21 | 22 | ||
22 | import {processPattern, arraysEqual, toLabelValueMap, fillPattern, fillPatternWithActions} from './widget-utils'; | 23 | import {processPattern, arraysEqual, toLabelValueMap, fillPattern, fillPatternWithActions} from './widget-utils'; |
23 | 24 | ||
@@ -83,6 +84,8 @@ export default class TbMapWidgetV2 { | @@ -83,6 +84,8 @@ export default class TbMapWidgetV2 { | ||
83 | settings.posFunction, | 84 | settings.posFunction, |
84 | settings.imageEntityAlias, | 85 | settings.imageEntityAlias, |
85 | settings.imageUrlAttribute); | 86 | settings.imageUrlAttribute); |
87 | + } else if (mapProvider === 'tencent-map') { | ||
88 | + this.map = new TbTencentMap($element,this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.tmApiKey, settings.tmDefaultMapType); | ||
86 | } | 89 | } |
87 | } | 90 | } |
88 | 91 | ||
@@ -466,6 +469,8 @@ export default class TbMapWidgetV2 { | @@ -466,6 +469,8 @@ export default class TbMapWidgetV2 { | ||
466 | schema = angular.copy(openstreetMapSettingsSchema); | 469 | schema = angular.copy(openstreetMapSettingsSchema); |
467 | } else if (mapProvider === 'image-map') { | 470 | } else if (mapProvider === 'image-map') { |
468 | return imageMapSettingsSchema; | 471 | return imageMapSettingsSchema; |
472 | + } else if (mapProvider === 'tencent-map') { | ||
473 | + schema = angular.copy(tencentMapSettingsSchema); | ||
469 | } | 474 | } |
470 | angular.merge(schema.schema.properties, commonMapSettingsSchema.schema.properties); | 475 | angular.merge(schema.schema.properties, commonMapSettingsSchema.schema.properties); |
471 | schema.schema.required = schema.schema.required.concat(commonMapSettingsSchema.schema.required); | 476 | schema.schema.required = schema.schema.required.concat(commonMapSettingsSchema.schema.required); |
@@ -544,7 +549,51 @@ const googleMapSettingsSchema = | @@ -544,7 +549,51 @@ const googleMapSettingsSchema = | ||
544 | } | 549 | } |
545 | ] | 550 | ] |
546 | }; | 551 | }; |
547 | - | 552 | + |
553 | +const tencentMapSettingsSchema = | ||
554 | + { | ||
555 | + "schema":{ | ||
556 | + "title":"Tencent Map Configuration", | ||
557 | + "type":"object", | ||
558 | + "properties":{ | ||
559 | + "tmApiKey":{ | ||
560 | + "title":"Tencent Maps API Key", | ||
561 | + "type":"string" | ||
562 | + }, | ||
563 | + "tmDefaultMapType":{ | ||
564 | + "title":"Default map type", | ||
565 | + "type":"string", | ||
566 | + "default":"roadmap" | ||
567 | + } | ||
568 | + }, | ||
569 | + "required":[ | ||
570 | + "tmApiKey" | ||
571 | + ] | ||
572 | + }, | ||
573 | + "form":[ | ||
574 | + "tmApiKey", | ||
575 | + { | ||
576 | + "key":"tmDefaultMapType", | ||
577 | + "type":"rc-select", | ||
578 | + "multiple":false, | ||
579 | + "items":[ | ||
580 | + { | ||
581 | + "value":"roadmap", | ||
582 | + "label":"Roadmap" | ||
583 | + }, | ||
584 | + { | ||
585 | + "value":"satellite", | ||
586 | + "label":"Satellite" | ||
587 | + }, | ||
588 | + { | ||
589 | + "value":"hybrid", | ||
590 | + "label":"Hybrid" | ||
591 | + }, | ||
592 | + ] | ||
593 | + } | ||
594 | + ] | ||
595 | + }; | ||
596 | + | ||
548 | const openstreetMapSettingsSchema = | 597 | const openstreetMapSettingsSchema = |
549 | { | 598 | { |
550 | "schema":{ | 599 | "schema":{ |
ui/src/app/widget/lib/tencent-map.js
0 → 100644
1 | +/* | ||
2 | + * Copyright © 2016-2017 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +var tmGlobals = { | ||
18 | + loadingTmId: null, | ||
19 | + tmApiKeys: {} | ||
20 | +} | ||
21 | + | ||
22 | +export default class TbTencentMap { | ||
23 | + constructor($containerElement,utils, initCallback, defaultZoomLevel, dontFitMapBounds, minZoomLevel, tmApiKey, tmDefaultMapType) { | ||
24 | + var tbMap = this; | ||
25 | + this.utils = utils; | ||
26 | + this.defaultZoomLevel = defaultZoomLevel; | ||
27 | + this.dontFitMapBounds = dontFitMapBounds; | ||
28 | + this.minZoomLevel = minZoomLevel; | ||
29 | + this.tooltips = []; | ||
30 | + this.defaultMapType = tmDefaultMapType; | ||
31 | + | ||
32 | + function clearGlobalId() { | ||
33 | + if (tmGlobals.loadingTmId && tmGlobals.loadingTmId === tbMap.mapId) { | ||
34 | + tmGlobals.loadingTmId = null; | ||
35 | + } | ||
36 | + } | ||
37 | + | ||
38 | + function displayError(message) { | ||
39 | + $containerElement.html( // eslint-disable-line angular/angularelement | ||
40 | + "<div class='error'>"+ message + "</div>" | ||
41 | + ); | ||
42 | + } | ||
43 | + | ||
44 | + function initTencentMap() { | ||
45 | + tbMap.map = new qq.maps.Map($containerElement[0], { // eslint-disable-line no-undef | ||
46 | + scrollwheel: true, | ||
47 | + mapTypeId: getTencentMapTypeId(tbMap.defaultMapType), | ||
48 | + zoom: tbMap.defaultZoomLevel || 8 | ||
49 | + }); | ||
50 | + | ||
51 | + if (initCallback) { | ||
52 | + initCallback(); | ||
53 | + } | ||
54 | + } | ||
55 | + | ||
56 | + /* eslint-disable no-undef */ | ||
57 | + | ||
58 | + function getTencentMapTypeId(mapType) { | ||
59 | + var mapTypeId =qq.maps.MapTypeId.ROADMAP; | ||
60 | + if (mapType) { | ||
61 | + if (mapType === 'hybrid') { | ||
62 | + mapTypeId = qq.maps.MapTypeId.HYBRID; | ||
63 | + } else if (mapType === 'satellite') { | ||
64 | + mapTypeId = qq.maps.MapTypeId.SATELLITE; | ||
65 | + } else if (mapType === 'terrain') { | ||
66 | + mapTypeId = qq.maps.MapTypeId.ROADMAP; | ||
67 | + } | ||
68 | + } | ||
69 | + return mapTypeId; | ||
70 | + } | ||
71 | + | ||
72 | + /* eslint-enable no-undef */ | ||
73 | + | ||
74 | + this.mapId = '' + Math.random().toString(36).substr(2, 9); | ||
75 | + this.apiKey = tmApiKey || '84d6d83e0e51e481e50454ccbe8986b'; | ||
76 | + | ||
77 | + window.gm_authFailure = function() { // eslint-disable-line no-undef, angular/window-service | ||
78 | + if (tmGlobals.loadingTmId && tmGlobals.loadingTmId === tbMap.mapId) { | ||
79 | + tmGlobals.loadingTmId = null; | ||
80 | + tmGlobals.tmApiKeys[tbMap.apiKey].error = 'Unable to authentificate for tencent Map API.</br>Please check your API key.'; | ||
81 | + displayError(tmGlobals.tmApiKeys[tbMap.apiKey].error); | ||
82 | + } | ||
83 | + }; | ||
84 | + | ||
85 | + this.initMapFunctionName = 'initTencentMap_' + this.mapId; | ||
86 | + | ||
87 | + window[this.initMapFunctionName] = function() { // eslint-disable-line no-undef, angular/window-service | ||
88 | + initTencentMap(); | ||
89 | + }; | ||
90 | + if (this.apiKey && this.apiKey.length > 0) { | ||
91 | + if (tmGlobals.tmApiKeys[this.apiKey]) { | ||
92 | + if (tmGlobals.tmApiKeys[this.apiKey].error) { | ||
93 | + displayError(tmGlobals.tmApiKeys[this.apiKey].error); | ||
94 | + } else if (tmGlobals.tmApiKeys[this.apiKey].loaded) { | ||
95 | + initTencentMap(); | ||
96 | + } else { | ||
97 | + tmGlobals.tmApiKeys[this.apiKey].pendingInits.push(initTencentMap); | ||
98 | + } | ||
99 | + } else { | ||
100 | + tmGlobals.tmApiKeys[this.apiKey] = { | ||
101 | + loaded: false, | ||
102 | + pendingInits: [] | ||
103 | + }; | ||
104 | + var tencentMapScriptRes = 'http://map.qq.com/api/js?v=2.exp&key='+this.apiKey+'&callback='+this.initMapFunctionName; | ||
105 | + | ||
106 | + tmGlobals.loadingTmId = this.mapId; | ||
107 | + lazyLoad.load({ type: 'js', path: tencentMapScriptRes }).then( // eslint-disable-line no-undef | ||
108 | + function success() { | ||
109 | + setTimeout(clearGlobalId, 2000); // eslint-disable-line no-undef, angular/timeout-service | ||
110 | + }, | ||
111 | + function fail(e) { | ||
112 | + clearGlobalId(); | ||
113 | + tmGlobals.tmApiKeys[tbMap.apiKey].error = 'tencent map api load failed!</br>'+e; | ||
114 | + displayError(tmGlobals.tmApiKeys[tbMap.apiKey].error); | ||
115 | + } | ||
116 | + ); | ||
117 | + } | ||
118 | + } else { | ||
119 | + displayError('No tencent Map Api Key provided!'); | ||
120 | + } | ||
121 | + } | ||
122 | + | ||
123 | + inited() { | ||
124 | + return angular.isDefined(this.map); | ||
125 | + } | ||
126 | + | ||
127 | + /* eslint-disable no-undef,no-unused-vars*/ | ||
128 | + updateMarkerLabel(marker, settings) { | ||
129 | + | ||
130 | + } | ||
131 | + /* eslint-enable no-undef,no-unused-vars */ | ||
132 | + | ||
133 | + /* eslint-disable no-undef,no-unused-vars */ | ||
134 | + updateMarkerColor(marker, color) { | ||
135 | + this.createDefaultMarkerIcon(marker, color, (icon) => { | ||
136 | + marker.setIcon(icon); | ||
137 | + }); | ||
138 | + } | ||
139 | + /* eslint-enable no-undef,,no-unused-vars */ | ||
140 | + | ||
141 | + /* eslint-disable no-undef */ | ||
142 | + updateMarkerIcon(marker, settings) { | ||
143 | + this.createMarkerIcon(marker, settings, (icon) => { | ||
144 | + marker.setIcon(icon); | ||
145 | + }); | ||
146 | + } | ||
147 | + /* eslint-disable no-undef */ | ||
148 | + | ||
149 | + /* eslint-disable no-undef */ | ||
150 | + createMarkerIcon(marker, settings, onMarkerIconReady) { | ||
151 | + var currentImage = settings.currentImage; | ||
152 | + var gMap = this; | ||
153 | + if (currentImage && currentImage.url) { | ||
154 | + this.utils.loadImageAspect(currentImage.url).then( | ||
155 | + (aspect) => { | ||
156 | + if (aspect) { | ||
157 | + var width; | ||
158 | + var height; | ||
159 | + if (aspect > 1) { | ||
160 | + width = currentImage.size; | ||
161 | + height = currentImage.size / aspect; | ||
162 | + } else { | ||
163 | + width = currentImage.size * aspect; | ||
164 | + height = currentImage.size; | ||
165 | + } | ||
166 | + | ||
167 | + var icon = new qq.maps.MarkerImage(currentImage.url, | ||
168 | + qq.maps.Size(width, height), | ||
169 | + new qq.maps.Point(0,0), | ||
170 | + new qq.maps.Point(10, 37)); | ||
171 | + | ||
172 | + onMarkerIconReady(icon); | ||
173 | + } else { | ||
174 | + gMap.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | ||
175 | + } | ||
176 | + } | ||
177 | + ); | ||
178 | + } else { | ||
179 | + this.createDefaultMarkerIcon(marker, settings.color, onMarkerIconReady); | ||
180 | + } | ||
181 | + } | ||
182 | + /* eslint-enable no-undef */ | ||
183 | + | ||
184 | + /* eslint-disable no-undef */ | ||
185 | + createDefaultMarkerIcon(marker, color, onMarkerIconReady) { | ||
186 | + /* var pinColor = color.substr(1);*/ | ||
187 | + var icon = new qq.maps.MarkerImage("http://api.map.qq.com/doc/img/nilt.png", | ||
188 | + new qq.maps.Size(40, 37), | ||
189 | + new qq.maps.Point(0,0), | ||
190 | + new qq.maps.Point(10, 37)); | ||
191 | + | ||
192 | + onMarkerIconReady(icon); | ||
193 | + } | ||
194 | + /* eslint-enable no-undef */ | ||
195 | + | ||
196 | + /* eslint-disable no-undef */ | ||
197 | + createMarker(location, settings, onClickListener, markerArgs) { | ||
198 | + var marker = new qq.maps.Marker({ | ||
199 | + map: this.map, | ||
200 | + position:location | ||
201 | + }); | ||
202 | + | ||
203 | + var gMap = this; | ||
204 | + this.createMarkerIcon(marker, settings, (icon) => { | ||
205 | + marker.setIcon(icon); | ||
206 | + marker.setMap(gMap.map) | ||
207 | + }); | ||
208 | + | ||
209 | + if (settings.displayTooltip) { | ||
210 | + this.createTooltip(marker, settings.tooltipPattern, settings.tooltipReplaceInfo, settings.autocloseTooltip, markerArgs); | ||
211 | + } | ||
212 | + | ||
213 | + if (onClickListener) { | ||
214 | + qq.maps.event.addListener(marker, 'click', onClickListener); | ||
215 | + } | ||
216 | + | ||
217 | + return marker; | ||
218 | + } | ||
219 | + | ||
220 | + /* eslint-disable no-undef */ | ||
221 | + removeMarker(marker) { | ||
222 | + marker.setMap(null); | ||
223 | + } | ||
224 | + | ||
225 | + /* eslint-enable no-undef */ | ||
226 | + | ||
227 | + /* eslint-disable no-undef */ | ||
228 | + createTooltip(marker, pattern, replaceInfo, autoClose, markerArgs) { | ||
229 | + var popup = new qq.maps.InfoWindow({ | ||
230 | + map :this.map | ||
231 | + }); | ||
232 | + var map = this; | ||
233 | + qq.maps.event.addListener(marker, 'click', function() { | ||
234 | + if (autoClose) { | ||
235 | + map.tooltips.forEach((tooltip) => { | ||
236 | + tooltip.popup.close(); | ||
237 | + }); | ||
238 | + } | ||
239 | + popup.open(); | ||
240 | + popup.setPosition(marker); | ||
241 | + }); | ||
242 | + this.tooltips.push( { | ||
243 | + markerArgs: markerArgs, | ||
244 | + popup: popup, | ||
245 | + pattern: pattern, | ||
246 | + replaceInfo: replaceInfo | ||
247 | + }); | ||
248 | + } | ||
249 | + /* eslint-enable no-undef */ | ||
250 | + | ||
251 | + /* eslint-disable no-undef */ | ||
252 | + updatePolylineColor(polyline, settings, color) { | ||
253 | + var options = { | ||
254 | + path: polyline.getPath(), | ||
255 | + strokeColor: color, | ||
256 | + strokeOpacity: settings.strokeOpacity, | ||
257 | + strokeWeight: settings.strokeWeight, | ||
258 | + map: this.map | ||
259 | + }; | ||
260 | + polyline.setOptions(options); | ||
261 | + } | ||
262 | + /* eslint-enable no-undef */ | ||
263 | + | ||
264 | + /* eslint-disable no-undef */ | ||
265 | + createPolyline(locations, settings) { | ||
266 | + var polyline = new qq.maps.Polyline({ | ||
267 | + path: locations, | ||
268 | + strokeColor: settings.color, | ||
269 | + strokeOpacity: settings.strokeOpacity, | ||
270 | + strokeWeight: settings.strokeWeight, | ||
271 | + map: this.map | ||
272 | + }); | ||
273 | + | ||
274 | + return polyline; | ||
275 | + } | ||
276 | + /* eslint-enable no-undef */ | ||
277 | + | ||
278 | + removePolyline(polyline) { | ||
279 | + polyline.setMap(null); | ||
280 | + } | ||
281 | + | ||
282 | + /* eslint-disable no-undef ,no-unused-vars*/ | ||
283 | + fitBounds(bounds) { | ||
284 | + if (this.dontFitMapBounds && this.defaultZoomLevel) { | ||
285 | + this.map.setZoom(this.defaultZoomLevel); | ||
286 | + this.map.setCenter(bounds.getCenter()); | ||
287 | + } else { | ||
288 | + var tbMap = this; | ||
289 | + qq.maps.event.addListenerOnce(this.map, 'bounds_changed', function() { // eslint-disable-line no-undef | ||
290 | + if (!tbMap.defaultZoomLevel && tbMap.map.getZoom() > tbMap.minZoomLevel) { | ||
291 | + tbMap.map.setZoom(tbMap.minZoomLevel); | ||
292 | + } | ||
293 | + }); | ||
294 | + this.map.fitBounds(bounds); | ||
295 | + } | ||
296 | + } | ||
297 | + /* eslint-enable no-undef,no-unused-vars */ | ||
298 | + | ||
299 | + createLatLng(lat, lng) { | ||
300 | + return new qq.maps.LatLng(lat, lng); // eslint-disable-line no-undef | ||
301 | + } | ||
302 | + | ||
303 | + extendBoundsWithMarker(bounds, marker) { | ||
304 | + bounds.extend(marker.getPosition()); | ||
305 | + } | ||
306 | + | ||
307 | + getMarkerPosition(marker) { | ||
308 | + return marker.getPosition(); | ||
309 | + } | ||
310 | + | ||
311 | + setMarkerPosition(marker, latLng) { | ||
312 | + marker.setPosition(latLng); | ||
313 | + } | ||
314 | + | ||
315 | + getPolylineLatLngs(polyline) { | ||
316 | + return polyline.getPath().getArray(); | ||
317 | + } | ||
318 | + | ||
319 | + setPolylineLatLngs(polyline, latLngs) { | ||
320 | + polyline.setPath(latLngs); | ||
321 | + } | ||
322 | + | ||
323 | + createBounds() { | ||
324 | + return new qq.maps.LatLngBounds(); // eslint-disable-line no-undef | ||
325 | + } | ||
326 | + | ||
327 | + extendBounds(bounds, polyline) { | ||
328 | + if (polyline && polyline.getPath()) { | ||
329 | + var locations = polyline.getPath(); | ||
330 | + for (var i = 0; i < locations.getLength(); i++) { | ||
331 | + bounds.extend(locations.getAt(i)); | ||
332 | + } | ||
333 | + } | ||
334 | + } | ||
335 | + | ||
336 | + invalidateSize() { | ||
337 | + qq.maps.event.trigger(this.map, "resize"); // eslint-disable-line no-undef | ||
338 | + } | ||
339 | + | ||
340 | + getTooltips() { | ||
341 | + return this.tooltips; | ||
342 | + } | ||
343 | + | ||
344 | +} |