Showing
12 changed files
with
158 additions
and
67 deletions
@@ -1897,6 +1897,11 @@ | @@ -1897,6 +1897,11 @@ | ||
1897 | "@types/geojson": "7946.0.7" | 1897 | "@types/geojson": "7946.0.7" |
1898 | } | 1898 | } |
1899 | }, | 1899 | }, |
1900 | + "@types/lodash": { | ||
1901 | + "version": "4.14.149", | ||
1902 | + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", | ||
1903 | + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==" | ||
1904 | + }, | ||
1900 | "@types/minimatch": { | 1905 | "@types/minimatch": { |
1901 | "version": "3.0.3", | 1906 | "version": "3.0.3", |
1902 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", | 1907 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", |
@@ -38,6 +38,7 @@ | @@ -38,6 +38,7 @@ | ||
38 | "@ngx-share/core": "^7.1.4", | 38 | "@ngx-share/core": "^7.1.4", |
39 | "@ngx-translate/core": "^12.1.1", | 39 | "@ngx-translate/core": "^12.1.1", |
40 | "@ngx-translate/http-loader": "^4.0.0", | 40 | "@ngx-translate/http-loader": "^4.0.0", |
41 | + "@types/lodash": "^4.14.149", | ||
41 | "ace-builds": "^1.4.8", | 42 | "ace-builds": "^1.4.8", |
42 | "angular-gridster2": "^9.0.1", | 43 | "angular-gridster2": "^9.0.1", |
43 | "angular2-hotkeys": "^2.1.5", | 44 | "angular2-hotkeys": "^2.1.5", |
@@ -101,7 +101,7 @@ export function isNumber(value: any): boolean { | @@ -101,7 +101,7 @@ export function isNumber(value: any): boolean { | ||
101 | } | 101 | } |
102 | 102 | ||
103 | export function isNumeric(value: any): boolean { | 103 | export function isNumeric(value: any): boolean { |
104 | - return (value - parseFloat( value ) + 1) >= 0; | 104 | + return (value - parseFloat(value) + 1) >= 0; |
105 | } | 105 | } |
106 | 106 | ||
107 | export function isString(value: any): boolean { | 107 | export function isString(value: any): boolean { |
@@ -226,9 +226,9 @@ function hashCode(str) { | @@ -226,9 +226,9 @@ function hashCode(str) { | ||
226 | var i, char; | 226 | var i, char; |
227 | if (str.length == 0) return hash; | 227 | if (str.length == 0) return hash; |
228 | for (i = 0; i < str.length; i++) { | 228 | for (i = 0; i < str.length; i++) { |
229 | - char = str.charCodeAt(i); | ||
230 | - hash = ((hash << 5) - hash) + char; | ||
231 | - hash = hash & hash; // Convert to 32bit integer | 229 | + char = str.charCodeAt(i); |
230 | + hash = ((hash << 5) - hash) + char; | ||
231 | + hash = hash & hash; // Convert to 32bit integer | ||
232 | } | 232 | } |
233 | return hash; | 233 | return hash; |
234 | } | 234 | } |
@@ -424,24 +424,24 @@ export function getDescendantProp(obj: any, path: string): any { | @@ -424,24 +424,24 @@ export function getDescendantProp(obj: any, path: string): any { | ||
424 | return path.split('.').reduce((acc, part) => acc && acc[part], obj); | 424 | return path.split('.').reduce((acc, part) => acc && acc[part], obj); |
425 | } | 425 | } |
426 | 426 | ||
427 | -export function imageLoader(imageUrl: string): Observable<HTMLImageElement>{ | 427 | +export function imageLoader(imageUrl: string): Observable<HTMLImageElement> { |
428 | const image = new Image(); | 428 | const image = new Image(); |
429 | - const imageLoad$ = fromEvent(image, 'load').pipe(map(event=>image)); | 429 | + const imageLoad$ = fromEvent(image, 'load').pipe(map(event => image)); |
430 | image.src = imageUrl; | 430 | image.src = imageUrl; |
431 | return imageLoad$; | 431 | return imageLoad$; |
432 | } | 432 | } |
433 | 433 | ||
434 | const imageAspectMap = {}; | 434 | const imageAspectMap = {}; |
435 | 435 | ||
436 | -export function aspectCache(imageUrl: string): Observable<number>{ | ||
437 | - if(imageUrl?.length){ | 436 | +export function aspectCache(imageUrl: string): Observable<number> { |
437 | + if (imageUrl?.length) { | ||
438 | const hash = hashCode(imageUrl); | 438 | const hash = hashCode(imageUrl); |
439 | let aspect = imageAspectMap[hash]; | 439 | let aspect = imageAspectMap[hash]; |
440 | - if(aspect){ | 440 | + if (aspect) { |
441 | return of(aspect); | 441 | return of(aspect); |
442 | } | 442 | } |
443 | - else return imageLoader(imageUrl).pipe(map(image=>{ | ||
444 | - aspect = image.width/image.height; | 443 | + else return imageLoader(imageUrl).pipe(map(image => { |
444 | + aspect = image.width / image.height; | ||
445 | imageAspectMap[hash] = aspect; | 445 | imageAspectMap[hash] = aspect; |
446 | return aspect; | 446 | return aspect; |
447 | })) | 447 | })) |
@@ -9,11 +9,13 @@ import { MapOptions, MarkerSettings } from './map-models'; | @@ -9,11 +9,13 @@ import { MapOptions, MarkerSettings } from './map-models'; | ||
9 | import { Marker } from './markers'; | 9 | import { Marker } from './markers'; |
10 | import { Observable, of, BehaviorSubject, Subject } from 'rxjs'; | 10 | import { Observable, of, BehaviorSubject, Subject } from 'rxjs'; |
11 | import { filter } from 'rxjs/operators'; | 11 | import { filter } from 'rxjs/operators'; |
12 | +import { Polyline } from './polyline'; | ||
12 | 13 | ||
13 | -export default class LeafletMap { | 14 | +export default abstract class LeafletMap { |
14 | 15 | ||
15 | - markers = []; | 16 | + markers: Map<string, Marker> = new Map(); |
16 | tooltips = []; | 17 | tooltips = []; |
18 | + poly: Polyline; | ||
17 | map: L.Map; | 19 | map: L.Map; |
18 | map$: BehaviorSubject<L.Map> = new BehaviorSubject(null); | 20 | map$: BehaviorSubject<L.Map> = new BehaviorSubject(null); |
19 | ready$: Observable<L.Map> = this.map$.pipe(filter(map => !!map)); | 21 | ready$: Observable<L.Map> = this.map$.pipe(filter(map => !!map)); |
@@ -22,6 +24,7 @@ export default class LeafletMap { | @@ -22,6 +24,7 @@ export default class LeafletMap { | ||
22 | 24 | ||
23 | 25 | ||
24 | constructor($container: HTMLElement, options: MapOptions) { | 26 | constructor($container: HTMLElement, options: MapOptions) { |
27 | + console.log("LeafletMap -> constructor -> options", options) | ||
25 | this.options = options; | 28 | this.options = options; |
26 | } | 29 | } |
27 | 30 | ||
@@ -123,29 +126,69 @@ export default class LeafletMap { | @@ -123,29 +126,69 @@ export default class LeafletMap { | ||
123 | return this.map.getCenter(); | 126 | return this.map.getCenter(); |
124 | } | 127 | } |
125 | 128 | ||
126 | - convertPosition(expression: L.LatLngExpression | { x, y }): L.LatLngExpression { | ||
127 | - return expression as L.LatLngExpression; | 129 | + convertPosition(expression: any): L.LatLng { |
130 | + return L.latLng(expression[this.options.latKeyName], expression[this.options.lngKeyName]) as L.LatLng; | ||
128 | } | 131 | } |
129 | 132 | ||
130 | ////Markers | 133 | ////Markers |
134 | + updateMarkers(markersData) { | ||
135 | + markersData.forEach(data => { | ||
136 | + if (this.markers.get(data.aliasName)) { | ||
137 | + this.updateMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings) | ||
138 | + } | ||
139 | + else { | ||
140 | + this.createMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings); | ||
141 | + } | ||
142 | + }); | ||
143 | + } | ||
131 | 144 | ||
132 | - | ||
133 | - createMarker(location, settings: MarkerSettings) { | 145 | + private createMarker(key, location, settings: MarkerSettings) { |
134 | this.ready$.subscribe(() => { | 146 | this.ready$.subscribe(() => { |
135 | let defaultSettings: MarkerSettings = { | 147 | let defaultSettings: MarkerSettings = { |
136 | color: '#FD2785' | 148 | color: '#FD2785' |
137 | } | 149 | } |
138 | - this.markers.push(new Marker(this.map, this.convertPosition(location), { ...defaultSettings, ...settings })) | 150 | + this.markers.set(key, new Marker(this.map, location, { ...defaultSettings, ...settings })) |
139 | }); | 151 | }); |
140 | } | 152 | } |
141 | 153 | ||
142 | - updateMarker() { | 154 | + private updateMarker(key, location: L.LatLng, settings: MarkerSettings) { |
155 | + const marker: Marker = this.markers.get(key); | ||
156 | + if (!location.equals(marker.location)) { | ||
157 | + marker.updateMarkerPosition(location); | ||
158 | + } | ||
159 | + //other implements later | ||
143 | 160 | ||
144 | } | 161 | } |
145 | 162 | ||
146 | - deleteMarker() { | 163 | + private deleteMarker() { |
147 | 164 | ||
148 | } | 165 | } |
149 | 166 | ||
167 | + //polyline | ||
168 | + | ||
169 | + updatePolylines(polyData) { | ||
170 | + if (this.poly) { | ||
150 | 171 | ||
172 | + } | ||
173 | + | ||
174 | + else { | ||
175 | + this.map$ | ||
176 | + this.createPolyline(polyData.map(data => this.convertPosition(data)), this.options); | ||
177 | + } | ||
178 | + | ||
179 | + /* markersData.forEach(data => { | ||
180 | + if (this.markers.get(data.aliasName)) { | ||
181 | + this.updateMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings) | ||
182 | + } | ||
183 | + else { | ||
184 | + this.createMarker(data.aliasName, this.convertPosition(data), this.options as MarkerSettings); | ||
185 | + } | ||
186 | + });*/ | ||
187 | + } | ||
188 | + | ||
189 | + createPolyline(locations, settings) { | ||
190 | + this.ready$.subscribe(() => | ||
191 | + this.poly = new Polyline(this.map, locations, settings) | ||
192 | + ) | ||
193 | + } | ||
151 | } | 194 | } |
@@ -4,6 +4,10 @@ export interface MapOptions { | @@ -4,6 +4,10 @@ export interface MapOptions { | ||
4 | dontFitMapBounds?: boolean, | 4 | dontFitMapBounds?: boolean, |
5 | disableScrollZooming?: boolean, | 5 | disableScrollZooming?: boolean, |
6 | minZoomLevel?: number, | 6 | minZoomLevel?: number, |
7 | + latKeyName?: string, | ||
8 | + lngKeyName?: string, | ||
9 | + xPosKeyName?: string, | ||
10 | + yPosKeyName?: string, | ||
7 | mapProvider: MapProviders, | 11 | mapProvider: MapProviders, |
8 | mapUrl?: string; | 12 | mapUrl?: string; |
9 | credentials?: any, // declare credentials format | 13 | credentials?: any, // declare credentials format |
@@ -19,9 +23,9 @@ export enum MapProviders { | @@ -19,9 +23,9 @@ export enum MapProviders { | ||
19 | tencent = 'tencent-map' | 23 | tencent = 'tencent-map' |
20 | } | 24 | } |
21 | 25 | ||
22 | -export interface MarkerSettings{ | 26 | +export interface MarkerSettings { |
23 | showLabel?: boolean, | 27 | showLabel?: boolean, |
24 | draggable?: boolean, | 28 | draggable?: boolean, |
25 | displayTooltip?: boolean, | 29 | displayTooltip?: boolean, |
26 | - color: string | 30 | + color?: string |
27 | } | 31 | } |
@@ -13,44 +13,21 @@ import { | @@ -13,44 +13,21 @@ import { | ||
13 | } from './schemes'; | 13 | } from './schemes'; |
14 | import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface'; | 14 | import { MapWidgetStaticInterface, MapWidgetInterface } from './map-widget.interface'; |
15 | import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers'; | 15 | import { OpenStreetMap, TencentMap, GoogleMap, HEREMap, ImageMap } from './providers'; |
16 | - | ||
17 | - | ||
18 | -const providerSets = { | ||
19 | - 'openstreet-map': { | ||
20 | - MapClass: OpenStreetMap, | ||
21 | - schema: openstreetMapSettingsSchema, | ||
22 | - name: "Openstreet" | ||
23 | - }, | ||
24 | - 'tencent-map': { | ||
25 | - MapClass: TencentMap, | ||
26 | - schema: tencentMapSettingsSchema, | ||
27 | - name: "Tencent" | ||
28 | - }, | ||
29 | - 'google-map': { | ||
30 | - MapClass: GoogleMap, | ||
31 | - schema: googleMapSettingsSchema, | ||
32 | - name: "Openstreet" | ||
33 | - }, | ||
34 | - 'here': { | ||
35 | - MapClass: HEREMap, | ||
36 | - schema: hereMapSettingsSchema, | ||
37 | - name: "HERE" | ||
38 | - }, | ||
39 | - 'image-map': { | ||
40 | - MapClass: ImageMap, | ||
41 | - schema: imageMapSettingsSchema | ||
42 | - } | ||
43 | -} | 16 | +import { WidgetSubscription } from '@app/core/public-api'; |
17 | +import { parseData, parseArray } from './maps-utils'; | ||
44 | 18 | ||
45 | export let TbMapWidgetV2: MapWidgetStaticInterface; | 19 | export let TbMapWidgetV2: MapWidgetStaticInterface; |
46 | TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { | 20 | TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { |
47 | map: LeafletMap; | 21 | map: LeafletMap; |
48 | provider: MapProviders; | 22 | provider: MapProviders; |
49 | schema; | 23 | schema; |
24 | + data; | ||
50 | 25 | ||
51 | - constructor(mapProvider: MapProviders, drawRoutes, ctx, $element) { | ||
52 | - console.log(ctx.settings); | ||
53 | - | 26 | + constructor(mapProvider: MapProviders, private drawRoutes, ctx, $element) { |
27 | + console.log("TbMapWidgetV2 -> constructor -> ctx", ctx) | ||
28 | + // console.log(ctx.subscriptions, ctx.data, ctx.datasources); | ||
29 | + this.data = ctx.data; | ||
30 | + //this.subsciptions. | ||
54 | if (!$element) { | 31 | if (!$element) { |
55 | $element = ctx.$container[0]; | 32 | $element = ctx.$container[0]; |
56 | } | 33 | } |
@@ -71,17 +48,21 @@ TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { | @@ -71,17 +48,21 @@ TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { | ||
71 | if (!MapClass) { | 48 | if (!MapClass) { |
72 | return; | 49 | return; |
73 | } | 50 | } |
74 | - this.map = new MapClass($element, { ...baseOptions, ...ctx.settings }) | ||
75 | - if(mapProvider !== "image-map") | ||
76 | - this.map.createMarker({ lat: 0, lng: 0 }, { color: '#FD2785' }) | ||
77 | - else | ||
78 | - this.map.createMarker({ x: 500, y: 500 }, { color: '#6D2785' }); | 51 | + this.map = new MapClass($element, { ...baseOptions, ...ctx.settings }); |
79 | this.schema = providerSets[mapProvider]?.schema; | 52 | this.schema = providerSets[mapProvider]?.schema; |
80 | } | 53 | } |
81 | 54 | ||
82 | onInit() { | 55 | onInit() { |
83 | } | 56 | } |
84 | 57 | ||
58 | + update() { | ||
59 | + console.log(this.data,parseData(this.data) ); | ||
60 | + | ||
61 | + if (this.drawRoutes) | ||
62 | + this.map.updatePolylines(parseArray(this.data)); | ||
63 | + this.map.updateMarkers(parseData(this.data)); | ||
64 | + } | ||
65 | + | ||
85 | onDataUpdated() { | 66 | onDataUpdated() { |
86 | } | 67 | } |
87 | 68 | ||
@@ -173,4 +154,31 @@ TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { | @@ -173,4 +154,31 @@ TbMapWidgetV2 = class TbMapWidgetV2 implements MapWidgetInterface { | ||
173 | 154 | ||
174 | onDestroy() { | 155 | onDestroy() { |
175 | } | 156 | } |
157 | +} | ||
158 | + | ||
159 | +const providerSets = { | ||
160 | + 'openstreet-map': { | ||
161 | + MapClass: OpenStreetMap, | ||
162 | + schema: openstreetMapSettingsSchema, | ||
163 | + name: "Openstreet" | ||
164 | + }, | ||
165 | + 'tencent-map': { | ||
166 | + MapClass: TencentMap, | ||
167 | + schema: tencentMapSettingsSchema, | ||
168 | + name: "Tencent" | ||
169 | + }, | ||
170 | + 'google-map': { | ||
171 | + MapClass: GoogleMap, | ||
172 | + schema: googleMapSettingsSchema, | ||
173 | + name: "Openstreet" | ||
174 | + }, | ||
175 | + 'here': { | ||
176 | + MapClass: HEREMap, | ||
177 | + schema: hereMapSettingsSchema, | ||
178 | + name: "HERE" | ||
179 | + }, | ||
180 | + 'image-map': { | ||
181 | + MapClass: ImageMap, | ||
182 | + schema: imageMapSettingsSchema | ||
183 | + } | ||
176 | } | 184 | } |
1 | import L from 'leaflet'; | 1 | import L from 'leaflet'; |
2 | +import _ from 'lodash'; | ||
2 | 3 | ||
3 | export function createTooltip(target, settings, targetArgs?) { | 4 | export function createTooltip(target, settings, targetArgs?) { |
4 | var popup = L.popup(); | 5 | var popup = L.popup(); |
@@ -19,4 +20,27 @@ export function createTooltip(target, settings, targetArgs?) { | @@ -19,4 +20,27 @@ export function createTooltip(target, settings, targetArgs?) { | ||
19 | locationSettings: settings, | 20 | locationSettings: settings, |
20 | dsIndex: settings.dsIndex | 21 | dsIndex: settings.dsIndex |
21 | }; | 22 | }; |
23 | +} | ||
24 | + | ||
25 | +export function parseArray(input: any[]): any[] { | ||
26 | + let alliases: any = _(input).groupBy(el => el?.datasource?.aliasName).values().value(); | ||
27 | + return alliases.map(alliasArray => | ||
28 | + alliasArray[0].data.map((el, i) => { | ||
29 | + const obj = { aliasName: alliasArray[0]?.datasource?.aliasName }; | ||
30 | + alliasArray.forEach(el => { | ||
31 | + obj[el?.dataKey?.label] = el?.data[i][1] | ||
32 | + }); | ||
33 | + return obj; | ||
34 | + }) | ||
35 | + ).flat(); | ||
36 | +} | ||
37 | + | ||
38 | +export function parseData(input: any[]): any[] { | ||
39 | + return _(input).groupBy(el => el?.datasource?.aliasName).values().value().map(alliasArray => { | ||
40 | + const obj = { aliasName: alliasArray[0]?.datasource?.aliasName }; | ||
41 | + alliasArray.forEach(el => { | ||
42 | + obj[el?.dataKey?.label] = el?.data[0][1] | ||
43 | + }); | ||
44 | + return obj; | ||
45 | + }); | ||
22 | } | 46 | } |
@@ -7,13 +7,14 @@ import { aspectCache } from '@app/core/utils'; | @@ -7,13 +7,14 @@ import { aspectCache } from '@app/core/utils'; | ||
7 | export class Marker { | 7 | export class Marker { |
8 | 8 | ||
9 | leafletMarker: L.Marker; | 9 | leafletMarker: L.Marker; |
10 | - // map: L.Map; | ||
11 | 10 | ||
12 | tooltipOffset; | 11 | tooltipOffset; |
13 | tooltip; | 12 | tooltip; |
13 | + location; | ||
14 | 14 | ||
15 | constructor(private map: L.Map, location: L.LatLngExpression, settings: MarkerSettings, onClickListener?, markerArgs?, onDragendListener?) { | 15 | constructor(private map: L.Map, location: L.LatLngExpression, settings: MarkerSettings, onClickListener?, markerArgs?, onDragendListener?) { |
16 | //this.map = map; | 16 | //this.map = map; |
17 | + this.location = location; | ||
17 | this.leafletMarker = L.marker(location, { | 18 | this.leafletMarker = L.marker(location, { |
18 | draggable: settings.draggable | 19 | draggable: settings.draggable |
19 | }); | 20 | }); |
@@ -43,6 +44,10 @@ export class Marker { | @@ -43,6 +44,10 @@ export class Marker { | ||
43 | 44 | ||
44 | } | 45 | } |
45 | 46 | ||
47 | + updateMarkerPosition(position: L.LatLngExpression){ | ||
48 | + this.leafletMarker.setLatLng(position); | ||
49 | + } | ||
50 | + | ||
46 | updateMarkerLabel(settings) { | 51 | updateMarkerLabel(settings) { |
47 | this.leafletMarker.unbindTooltip(); | 52 | this.leafletMarker.unbindTooltip(); |
48 | if (settings.showLabel) | 53 | if (settings.showLabel) |
@@ -56,7 +61,7 @@ export class Marker { | @@ -56,7 +61,7 @@ export class Marker { | ||
56 | }); | 61 | }); |
57 | } | 62 | } |
58 | 63 | ||
59 | - updateMarkerIcon( settings) { | 64 | + updateMarkerIcon(settings) { |
60 | this.createMarkerIcon(settings, (iconInfo) => { | 65 | this.createMarkerIcon(settings, (iconInfo) => { |
61 | this.leafletMarker.setIcon(iconInfo.icon); | 66 | this.leafletMarker.setIcon(iconInfo.icon); |
62 | if (settings.showLabel) { | 67 | if (settings.showLabel) { |
@@ -2,10 +2,9 @@ import L from 'leaflet'; | @@ -2,10 +2,9 @@ import L from 'leaflet'; | ||
2 | 2 | ||
3 | export class Polyline { | 3 | export class Polyline { |
4 | 4 | ||
5 | - map: L.Map; | ||
6 | leafletPoly: L.Polyline; | 5 | leafletPoly: L.Polyline; |
7 | 6 | ||
8 | - constructor(locations, settings) { | 7 | + constructor(private map: L.Map, locations, settings) { |
9 | this.leafletPoly = L.polyline(locations, | 8 | this.leafletPoly = L.polyline(locations, |
10 | { | 9 | { |
11 | color: settings.color, | 10 | color: settings.color, |
@@ -101,13 +101,13 @@ export class ImageMap extends LeafletMap { | @@ -101,13 +101,13 @@ export class ImageMap extends LeafletMap { | ||
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | - convertPosition(expression: { x, y }): L.LatLngExpression { | ||
105 | - console.log("ImageMap -> expression", expression) | ||
106 | - return this.pointToLatLng(expression.x, expression.y) as L.LatLngExpression; | 104 | + convertPosition(expression): L.LatLng { |
105 | + return this.pointToLatLng( | ||
106 | + expression[this.options.xPosKeyName] * this.width, | ||
107 | + expression[this.options.yPosKeyName] * this.height); | ||
107 | } | 108 | } |
108 | 109 | ||
109 | - | ||
110 | - pointToLatLng(x, y) { | 110 | + pointToLatLng(x, y): L.LatLng { |
111 | return L.CRS.Simple.pointToLatLng({ x, y } as L.PointExpression, maxZoom - 1); | 111 | return L.CRS.Simple.pointToLatLng({ x, y } as L.PointExpression, maxZoom - 1); |
112 | } | 112 | } |
113 | 113 |