UI: Map - improve MapLibre GL integration.
This commit is contained in:
parent
0c2b6fb499
commit
f04303954a
@ -28,7 +28,6 @@
|
|||||||
"@flowjs/ngx-flow": "18.0.1",
|
"@flowjs/ngx-flow": "18.0.1",
|
||||||
"@geoman-io/leaflet-geoman-free": "2.17.0",
|
"@geoman-io/leaflet-geoman-free": "2.17.0",
|
||||||
"@iplab/ngx-color-picker": "^18.0.1",
|
"@iplab/ngx-color-picker": "^18.0.1",
|
||||||
"@maplibre/maplibre-gl-leaflet": "^0.0.22",
|
|
||||||
"@mat-datetimepicker/core": "~14.0.0",
|
"@mat-datetimepicker/core": "~14.0.0",
|
||||||
"@mdi/svg": "^7.4.47",
|
"@mdi/svg": "^7.4.47",
|
||||||
"@messageformat/core": "^3.4.0",
|
"@messageformat/core": "^3.4.0",
|
||||||
@ -65,7 +64,7 @@
|
|||||||
"leaflet.gridlayer.googlemutant": "0.14.1",
|
"leaflet.gridlayer.googlemutant": "0.14.1",
|
||||||
"leaflet.markercluster": "1.5.3",
|
"leaflet.markercluster": "1.5.3",
|
||||||
"libphonenumber-js": "^1.11.15",
|
"libphonenumber-js": "^1.11.15",
|
||||||
"maplibre-gl": "^4.7.1",
|
"maplibre-gl": "^5.2.0",
|
||||||
"marked": "~12.0.2",
|
"marked": "~12.0.2",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"moment-timezone": "^0.5.45",
|
"moment-timezone": "^0.5.45",
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
import L, { TB } from 'leaflet';
|
import L, { TB } from 'leaflet';
|
||||||
import { guid, isNotEmptyStr } from '@core/utils';
|
import { guid, isNotEmptyStr } from '@core/utils';
|
||||||
import 'leaflet-providers';
|
import 'leaflet-providers';
|
||||||
import '@maplibre/maplibre-gl-leaflet';
|
import { Map as MapLibreGLMap, LngLat as MapLibreGLLngLat } from 'maplibre-gl';
|
||||||
import '@geoman-io/leaflet-geoman-free';
|
import '@geoman-io/leaflet-geoman-free';
|
||||||
import 'leaflet.markercluster';
|
import 'leaflet.markercluster';
|
||||||
import { MatIconRegistry } from '@angular/material/icon';
|
import { MatIconRegistry } from '@angular/material/icon';
|
||||||
@ -27,7 +27,7 @@ import { of } from 'rxjs';
|
|||||||
|
|
||||||
L.MarkerCluster = L.MarkerCluster.mergeOptions({ pmIgnore: true });
|
L.MarkerCluster = L.MarkerCluster.mergeOptions({ pmIgnore: true });
|
||||||
|
|
||||||
class SidebarControl extends L.Control<TB.SidebarControlOptions> {
|
class SidebarControl extends L.Control<TB.SidebarControlOptions> implements L.TB.SidebarControl {
|
||||||
|
|
||||||
private readonly sidebar: JQuery<HTMLElement>;
|
private readonly sidebar: JQuery<HTMLElement>;
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ class SidebarControl extends L.Control<TB.SidebarControlOptions> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SidebarPaneControl<O extends TB.SidebarPaneControlOptions> extends L.Control<O> {
|
class SidebarPaneControl<O extends TB.SidebarPaneControlOptions> extends L.Control<O> implements L.TB.SidebarPaneControl<O> {
|
||||||
|
|
||||||
private button: JQuery<HTMLElement>;
|
private button: JQuery<HTMLElement>;
|
||||||
private $ui: JQuery<HTMLElement>;
|
private $ui: JQuery<HTMLElement>;
|
||||||
@ -155,7 +155,7 @@ class SidebarPaneControl<O extends TB.SidebarPaneControlOptions> extends L.Contr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LayersControl extends SidebarPaneControl<TB.LayersControlOptions> {
|
class LayersControl extends SidebarPaneControl<TB.LayersControlOptions> implements L.TB.LayersControl {
|
||||||
constructor(options: TB.LayersControlOptions) {
|
constructor(options: TB.LayersControlOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
}
|
}
|
||||||
@ -215,9 +215,6 @@ class LayersControl extends SidebarPaneControl<TB.LayersControlOptions> {
|
|||||||
if (!map.hasLayer(layerData.layer)) {
|
if (!map.hasLayer(layerData.layer)) {
|
||||||
map.addLayer(layerData.layer);
|
map.addLayer(layerData.layer);
|
||||||
map.attributionControl.setPrefix(layerData.attributionPrefix);
|
map.attributionControl.setPrefix(layerData.attributionPrefix);
|
||||||
if (layerData.onAdd) {
|
|
||||||
layerData.onAdd();
|
|
||||||
}
|
|
||||||
layers.forEach((other) => {
|
layers.forEach((other) => {
|
||||||
if (other.layer !== layerData.layer) {
|
if (other.layer !== layerData.layer) {
|
||||||
map.removeLayer(other.layer);
|
map.removeLayer(other.layer);
|
||||||
@ -238,12 +235,12 @@ class LayersControl extends SidebarPaneControl<TB.LayersControlOptions> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupsControl extends SidebarPaneControl<TB.GroupsControlOptions> {
|
class GroupsControl extends SidebarPaneControl<TB.GroupsControlOptions> implements L.TB.GroupsControl {
|
||||||
constructor(options: TB.GroupsControlOptions) {
|
constructor(options: TB.GroupsControlOptions) {
|
||||||
super(options);
|
super(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onAddPane(map: L.Map, button: JQuery<HTMLElement>, $ui: JQuery<HTMLElement>, toggle: (e: JQuery.MouseEventBase) => void) {
|
public onAddPane(map: L.Map, _button: JQuery<HTMLElement>, $ui: JQuery<HTMLElement>, _toggle: (e: JQuery.MouseEventBase) => void) {
|
||||||
const paneId = guid();
|
const paneId = guid();
|
||||||
const groups = this.options.groups;
|
const groups = this.options.groups;
|
||||||
const baseSection = $("<div>")
|
const baseSection = $("<div>")
|
||||||
@ -285,7 +282,7 @@ class GroupsControl extends SidebarPaneControl<TB.GroupsControlOptions> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TopToolbarButton {
|
class TopToolbarButton implements L.TB.TopToolbarButton {
|
||||||
private readonly button: JQuery<HTMLElement>;
|
private readonly button: JQuery<HTMLElement>;
|
||||||
private active = false;
|
private active = false;
|
||||||
private disabled = false;
|
private disabled = false;
|
||||||
@ -393,7 +390,7 @@ class TopToolbarButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToolbarButton {
|
class ToolbarButton implements L.TB.ToolbarButton {
|
||||||
private readonly id: string;
|
private readonly id: string;
|
||||||
private readonly button: JQuery<HTMLElement>;
|
private readonly button: JQuery<HTMLElement>;
|
||||||
private active = false;
|
private active = false;
|
||||||
@ -461,7 +458,7 @@ class ToolbarButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TopToolbarControl {
|
class TopToolbarControl implements L.TB.TopToolbarControl {
|
||||||
|
|
||||||
private readonly toolbarElement: JQuery<HTMLElement>;
|
private readonly toolbarElement: JQuery<HTMLElement>;
|
||||||
private buttons: Array<TopToolbarButton> = [];
|
private buttons: Array<TopToolbarButton> = [];
|
||||||
@ -490,7 +487,7 @@ class TopToolbarControl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ToolbarControl extends L.Control<L.ControlOptions> {
|
class ToolbarControl extends L.Control<L.ControlOptions> implements L.TB.ToolbarControl {
|
||||||
|
|
||||||
private buttonContainer: JQuery<HTMLElement>;
|
private buttonContainer: JQuery<HTMLElement>;
|
||||||
|
|
||||||
@ -516,7 +513,7 @@ class ToolbarControl extends L.Control<L.ControlOptions> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class BottomToolbarControl {
|
class BottomToolbarControl implements L.TB.BottomToolbarControl {
|
||||||
|
|
||||||
private readonly buttonContainer: JQuery<HTMLElement>;
|
private readonly buttonContainer: JQuery<HTMLElement>;
|
||||||
private toolbarButtons: ToolbarButton[] = [];
|
private toolbarButtons: ToolbarButton[] = [];
|
||||||
@ -575,35 +572,35 @@ class BottomToolbarControl {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sidebar = (options: TB.SidebarControlOptions): SidebarControl => {
|
const sidebar = (options: TB.SidebarControlOptions): L.TB.SidebarControl => {
|
||||||
return new SidebarControl(options);
|
return new SidebarControl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sidebarPane = <O extends TB.SidebarPaneControlOptions>(options: O): SidebarPaneControl<O> => {
|
const sidebarPane = <O extends TB.SidebarPaneControlOptions>(options: O): L.TB.SidebarPaneControl<O> => {
|
||||||
return new SidebarPaneControl(options);
|
return new SidebarPaneControl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const layers = (options: TB.LayersControlOptions): LayersControl => {
|
const layers = (options: TB.LayersControlOptions): L.TB.LayersControl => {
|
||||||
return new LayersControl(options);
|
return new LayersControl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups = (options: TB.GroupsControlOptions): GroupsControl => {
|
const groups = (options: TB.GroupsControlOptions): L.TB.GroupsControl => {
|
||||||
return new GroupsControl(options);
|
return new GroupsControl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const topToolbar = (options: TB.TopToolbarControlOptions): TopToolbarControl => {
|
const topToolbar = (options: TB.TopToolbarControlOptions): L.TB.TopToolbarControl => {
|
||||||
return new TopToolbarControl(options);
|
return new TopToolbarControl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolbar = (options: L.ControlOptions): ToolbarControl => {
|
const toolbar = (options: L.ControlOptions): L.TB.ToolbarControl => {
|
||||||
return new ToolbarControl(options);
|
return new ToolbarControl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bottomToolbar = (options: TB.BottomToolbarControlOptions): BottomToolbarControl => {
|
const bottomToolbar = (options: TB.BottomToolbarControlOptions): L.TB.BottomToolbarControl => {
|
||||||
return new BottomToolbarControl(options);
|
return new BottomToolbarControl(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChinaProvider extends L.TileLayer {
|
class ChinaProvider extends L.TileLayer implements L.TB.TileLayer.ChinaProvider {
|
||||||
|
|
||||||
static chinaProviders: L.TB.TileLayer.ChinaProvidersData = {
|
static chinaProviders: L.TB.TileLayer.ChinaProvidersData = {
|
||||||
Tencent: {
|
Tencent: {
|
||||||
@ -649,10 +646,299 @@ class ChinaProvider extends L.TileLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const chinaProvider = (type: string, options?: L.TileLayerOptions): ChinaProvider => {
|
const chinaProvider = (type: string, options?: L.TileLayerOptions): L.TB.TileLayer.ChinaProvider => {
|
||||||
return new ChinaProvider(type, options);
|
return new ChinaProvider(type, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MapLibreGLLayer extends L.Layer implements TB.MapLibreGL.MapLibreGLLayer {
|
||||||
|
|
||||||
|
options: TB.MapLibreGL.LeafletMapLibreGLMapOptions;
|
||||||
|
|
||||||
|
private readonly _throttledUpdate: () => void;
|
||||||
|
private _container: HTMLDivElement;
|
||||||
|
private _glMap: MapLibreGLMap;
|
||||||
|
private _actualCanvas: HTMLCanvasElement;
|
||||||
|
private _offset: L.Point;
|
||||||
|
private _zooming: boolean;
|
||||||
|
|
||||||
|
constructor(options: TB.MapLibreGL.LeafletMapLibreGLMapOptions) {
|
||||||
|
super();
|
||||||
|
options = {...options, ...{
|
||||||
|
updateInterval: 32,
|
||||||
|
padding: 0.1,
|
||||||
|
interactive: false,
|
||||||
|
pane: 'tilePane'
|
||||||
|
}};
|
||||||
|
options.attribution = this._loadAttribution(options);
|
||||||
|
this._prepareTransformRequest(options);
|
||||||
|
L.setOptions(this, options);
|
||||||
|
this._throttledUpdate = L.Util.throttle(this._update, this.options.updateInterval, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAdd(map: L.Map): this {
|
||||||
|
let update = false;
|
||||||
|
if (!this._container) {
|
||||||
|
this._initContainer();
|
||||||
|
} else {
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
const paneName = this.getPaneName();
|
||||||
|
map.getPane(paneName).appendChild(this._container);
|
||||||
|
this._initGL();
|
||||||
|
|
||||||
|
this._offset = this._map.containerPointToLayerPoint([0, 0]);
|
||||||
|
if ((this._map as any)._proxy && map.options.zoomAnimation) {
|
||||||
|
L.DomEvent.on((map as any)._proxy, L.DomUtil.TRANSITION_END, this._transitionEnd, this);
|
||||||
|
}
|
||||||
|
if (update) {
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemove(map: L.Map): this {
|
||||||
|
if ((this._map as any)._proxy && this._map.options.zoomAnimation) {
|
||||||
|
L.DomEvent.off((map as any)._proxy, L.DomUtil.TRANSITION_END, this._transitionEnd, this);
|
||||||
|
}
|
||||||
|
const paneName = this.getPaneName();
|
||||||
|
map.getPane(paneName).removeChild(this._container);
|
||||||
|
|
||||||
|
this._glMap.remove();
|
||||||
|
this._glMap = null;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEvents(): { [p: string]: L.LeafletEventHandlerFn } {
|
||||||
|
return {
|
||||||
|
move: this._throttledUpdate, // sensibly throttle updating while panning
|
||||||
|
zoomanim: this._animateZoom, // applys the zoom animation to the <canvas>
|
||||||
|
zoom: this._pinchZoom, // animate every zoom event for smoother pinch-zooming
|
||||||
|
zoomstart: this._zoomStart, // flag starting a zoom to disable panning
|
||||||
|
zoomend: this._zoomEnd,
|
||||||
|
resize: this._resize
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getMapLibreGLMap(): MapLibreGLMap {
|
||||||
|
return this._glMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCanvas(): HTMLCanvasElement {
|
||||||
|
return this._glMap.getCanvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSize(): L.Point {
|
||||||
|
return this._map.getSize().multiplyBy(1 + this.options.padding * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
getBounds(): L.LatLngBounds {
|
||||||
|
const halfSize = this.getSize().multiplyBy(0.5);
|
||||||
|
const center = this._map.latLngToContainerPoint(this._map.getCenter());
|
||||||
|
return L.latLngBounds(
|
||||||
|
this._map.containerPointToLatLng(center.subtract(halfSize)),
|
||||||
|
this._map.containerPointToLatLng(center.add(halfSize))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getContainer(): HTMLDivElement {
|
||||||
|
return this._container;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPaneName(): string {
|
||||||
|
return this._map.getPane(this.options.pane) ? this.options.pane : 'tilePane';
|
||||||
|
}
|
||||||
|
|
||||||
|
private _roundPoint(p: L.Point): L.Point {
|
||||||
|
return new L.Point(Math.round(p.x), Math.round(p.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _initContainer() {
|
||||||
|
const container = this._container = L.DomUtil.create('div', 'leaflet-gl-layer');
|
||||||
|
const size = this.getSize();
|
||||||
|
const offset = this._map.getSize().multiplyBy(this.options.padding);
|
||||||
|
container.style.width = size.x + 'px';
|
||||||
|
container.style.height = size.y + 'px';
|
||||||
|
const topLeft = this._map.containerPointToLayerPoint([0, 0]).subtract(offset);
|
||||||
|
L.DomUtil.setPosition(container, this._roundPoint(topLeft));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _initGL() {
|
||||||
|
const center = this._map.getCenter();
|
||||||
|
const options = L.extend({}, this.options, {
|
||||||
|
container: this._container,
|
||||||
|
center: [center.lng, center.lat],
|
||||||
|
zoom: this._map.getZoom() - 1,
|
||||||
|
attributionControl: false
|
||||||
|
});
|
||||||
|
this._glMap = new MapLibreGLMap(options);
|
||||||
|
this._glMap.setMaxBounds(null);
|
||||||
|
this._transformGL(this._glMap);
|
||||||
|
this._actualCanvas = this._glMap._canvas;
|
||||||
|
const canvas = this._actualCanvas;
|
||||||
|
L.DomUtil.addClass(canvas, 'leaflet-image-layer');
|
||||||
|
L.DomUtil.addClass(canvas, 'leaflet-zoom-animated');
|
||||||
|
if (this.options.interactive) {
|
||||||
|
L.DomUtil.addClass(canvas, 'leaflet-interactive');
|
||||||
|
}
|
||||||
|
if (this.options.className) {
|
||||||
|
L.DomUtil.addClass(canvas, this.options.className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _update() {
|
||||||
|
if (!this._map) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._offset = this._map.containerPointToLayerPoint([0, 0]);
|
||||||
|
|
||||||
|
if (this._zooming) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const size = this.getSize(),
|
||||||
|
container = this._container,
|
||||||
|
gl = this._glMap,
|
||||||
|
offset = this._map.getSize().multiplyBy(this.options.padding),
|
||||||
|
topLeft = this._map.containerPointToLayerPoint([0, 0]).subtract(offset);
|
||||||
|
|
||||||
|
L.DomUtil.setPosition(container, this._roundPoint(topLeft));
|
||||||
|
|
||||||
|
this._transformGL(gl);
|
||||||
|
|
||||||
|
if (gl.transform.width !== size.x || gl.transform.height !== size.y) {
|
||||||
|
container.style.width = size.x + 'px';
|
||||||
|
container.style.height = size.y + 'px';
|
||||||
|
gl.resize();
|
||||||
|
} else {
|
||||||
|
gl._update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _transformGL(gl: MapLibreGLMap) {
|
||||||
|
const center = this._map.getCenter();
|
||||||
|
const tr = gl._getTransformForUpdate();
|
||||||
|
tr.setCenter(MapLibreGLLngLat.convert([center.lng, center.lat]));
|
||||||
|
tr.setZoom(this._map.getZoom() - 1);
|
||||||
|
gl.transform.apply(tr);
|
||||||
|
gl._fireMoveEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _pinchZoom() {
|
||||||
|
this._glMap.jumpTo({
|
||||||
|
zoom: this._map.getZoom() - 1,
|
||||||
|
center: this._map.getCenter()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _animateZoom(e: L.ZoomAnimEvent) {
|
||||||
|
const scale = this._map.getZoomScale(e.zoom);
|
||||||
|
const padding = this._map.getSize().multiplyBy(this.options.padding * scale);
|
||||||
|
const viewHalf = this.getSize().divideBy(2);
|
||||||
|
|
||||||
|
const topLeft = this._map.project(e.center, e.zoom)
|
||||||
|
.subtract(viewHalf)
|
||||||
|
.add((this._map as any)._getMapPanePos()
|
||||||
|
.add(padding)).round();
|
||||||
|
|
||||||
|
const offset = this._map.project(this._map.getBounds().getNorthWest(), e.zoom)
|
||||||
|
.subtract(topLeft);
|
||||||
|
|
||||||
|
L.DomUtil.setTransform(
|
||||||
|
this._actualCanvas,
|
||||||
|
offset.subtract(this._offset),
|
||||||
|
scale
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _zoomStart() {
|
||||||
|
this._zooming = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _zoomEnd() {
|
||||||
|
const scale = this._map.getZoomScale(this._map.getZoom());
|
||||||
|
L.DomUtil.setTransform(
|
||||||
|
this._actualCanvas,
|
||||||
|
null,
|
||||||
|
scale
|
||||||
|
);
|
||||||
|
this._zooming = false;
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _transitionEnd() {
|
||||||
|
L.Util.requestAnimFrame(() => {
|
||||||
|
const zoom = this._map.getZoom();
|
||||||
|
const center = this._map.getCenter();
|
||||||
|
const offset = this._map.latLngToContainerPoint(
|
||||||
|
this._map.getBounds().getNorthWest()
|
||||||
|
);
|
||||||
|
|
||||||
|
L.DomUtil.setTransform(this._actualCanvas, offset, 1);
|
||||||
|
|
||||||
|
this._glMap.once('moveend', () => {
|
||||||
|
this._zoomEnd();
|
||||||
|
});
|
||||||
|
this._glMap.jumpTo({
|
||||||
|
center: center,
|
||||||
|
zoom: zoom - 1
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _resize() {
|
||||||
|
this._transitionEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _loadAttribution(options: TB.MapLibreGL.LeafletMapLibreGLMapOptions): string {
|
||||||
|
if (options.attributionControl !== false && typeof options.attributionControl?.customAttribution === 'string') {
|
||||||
|
return options.attributionControl.customAttribution;
|
||||||
|
}
|
||||||
|
if (options.attributionControl !== false) {
|
||||||
|
const style = options.style;
|
||||||
|
if (typeof style !== 'string' && style?.sources) {
|
||||||
|
return Object.keys(style.sources)
|
||||||
|
.map((sourceId) => {
|
||||||
|
const source = style.sources[sourceId];
|
||||||
|
return (source && source.type !== 'video' && source.type !== 'image'
|
||||||
|
&& typeof source.attribution === 'string') ? source.attribution.trim() : null;
|
||||||
|
})
|
||||||
|
.filter(Boolean) // Remove null/undefined values
|
||||||
|
.join(', ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
private _prepareTransformRequest(options: TB.MapLibreGL.LeafletMapLibreGLMapOptions) {
|
||||||
|
if (!options.transformRequest) {
|
||||||
|
const style = options.style;
|
||||||
|
if (typeof style !== 'string' && style.glyphs) {
|
||||||
|
const glyphs = style.glyphs;
|
||||||
|
const glyphsRegexString = glyphs.replace(/\//g, '\\/').replace(/\./g, '\\.').replace('{fontstack}', '(.*)').replace('{range}', '(.*)');
|
||||||
|
const glyphsRegex = new RegExp(glyphsRegexString);
|
||||||
|
options.transformRequest = (url, resourceType) => {
|
||||||
|
if (resourceType === 'Glyphs' && glyphsRegex && glyphsRegex.test(url)) {
|
||||||
|
const res = glyphsRegex.exec(url);
|
||||||
|
if (res.length === 3) {
|
||||||
|
const fontStack = res[1];
|
||||||
|
const fonts = fontStack.split(',');
|
||||||
|
if (fonts.length > 1) {
|
||||||
|
const newFontStack = fonts[0];
|
||||||
|
url = url.replace(fontStack, newFontStack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {url};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapLibreGLLayer = (options: TB.MapLibreGL.LeafletMapLibreGLMapOptions): TB.MapLibreGL.MapLibreGLLayer => {
|
||||||
|
return new MapLibreGLLayer(options);
|
||||||
|
}
|
||||||
|
|
||||||
L.TB = L.TB || {
|
L.TB = L.TB || {
|
||||||
SidebarControl,
|
SidebarControl,
|
||||||
SidebarPaneControl,
|
SidebarPaneControl,
|
||||||
@ -675,5 +961,9 @@ L.TB = L.TB || {
|
|||||||
},
|
},
|
||||||
tileLayer: {
|
tileLayer: {
|
||||||
chinaProvider
|
chinaProvider
|
||||||
|
},
|
||||||
|
MapLibreGL: {
|
||||||
|
MapLibreGLLayer,
|
||||||
|
mapLibreGLLayer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,8 @@ import {
|
|||||||
HereMapLayerSettings,
|
HereMapLayerSettings,
|
||||||
MapLayerSettings,
|
MapLayerSettings,
|
||||||
MapProvider,
|
MapProvider,
|
||||||
OpenStreetMapLayerSettings, ReferenceLayerType,
|
OpenStreetMapLayerSettings,
|
||||||
|
ReferenceLayerType,
|
||||||
TencentMapLayerSettings
|
TencentMapLayerSettings
|
||||||
} from '@shared/models/widget/maps/map.models';
|
} from '@shared/models/widget/maps/map.models';
|
||||||
import { WidgetContext } from '@home/models/widget-component.models';
|
import { WidgetContext } from '@home/models/widget-component.models';
|
||||||
@ -37,13 +38,13 @@ import { CustomTranslatePipe } from '@shared/pipe/custom-translate.pipe';
|
|||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
import { catchError, map } from 'rxjs/operators';
|
import { catchError, map } from 'rxjs/operators';
|
||||||
import { ResourcesService } from '@core/services/resources.service';
|
import { ResourcesService } from '@core/services/resources.service';
|
||||||
import { StyleSpecification, VectorSourceSpecification } from '@maplibre/maplibre-gl-style-spec';
|
import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||||
import { ResourceType } from 'maplibre-gl';
|
|
||||||
|
|
||||||
const referenceLayerStyleUrlMap = new Map<ReferenceLayerType, string>(
|
const referenceLayerStyleUrlMap = new Map<ReferenceLayerType, string>(
|
||||||
[
|
[
|
||||||
[ReferenceLayerType.openstreetmap_hybrid, '/assets/map/openstreetmap_hybrid_reference_style.json'],
|
[ReferenceLayerType.openstreetmap_hybrid, '/assets/map/openstreetmap_hybrid_reference_style.json'],
|
||||||
[ReferenceLayerType.world_edition_hybrid, '/assets/map/world_edition_hybrid_reference_style.json']
|
[ReferenceLayerType.world_edition_hybrid, '/assets/map/world_edition_hybrid_reference_style.json'],
|
||||||
|
[ReferenceLayerType.enhanced_contrast_hybrid, '/assets/map/enhanced_contrast_hybrid_reference_style.json']
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -52,7 +53,6 @@ const referenceLayerCache = new Map<ReferenceLayerType, Observable<StyleSpecific
|
|||||||
interface TbMapLayerData {
|
interface TbMapLayerData {
|
||||||
layer: L.Layer;
|
layer: L.Layer;
|
||||||
attribution: boolean;
|
attribution: boolean;
|
||||||
onAdd?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class TbMapLayer<S extends MapLayerSettings> {
|
export abstract class TbMapLayer<S extends MapLayerSettings> {
|
||||||
@ -93,12 +93,7 @@ export abstract class TbMapLayer<S extends MapLayerSettings> {
|
|||||||
title: this.title(),
|
title: this.title(),
|
||||||
attributionPrefix: attributionPrefix,
|
attributionPrefix: attributionPrefix,
|
||||||
layer: layerData.layer,
|
layer: layerData.layer,
|
||||||
mini: miniLayerData.layer,
|
mini: miniLayerData.layer
|
||||||
onAdd: () => {
|
|
||||||
if (layerData.onAdd) {
|
|
||||||
layerData.onAdd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -125,10 +120,7 @@ export abstract class TbMapLayer<S extends MapLayerSettings> {
|
|||||||
referenceLayer.addTo(layer);
|
referenceLayer.addTo(layer);
|
||||||
return {
|
return {
|
||||||
layer,
|
layer,
|
||||||
attribution: !!baseLayer.getAttribution() || !!referenceLayer.getAttribution(),
|
attribution: !!baseLayer.getAttribution() || !!referenceLayer.getAttribution()
|
||||||
onAdd: () => {
|
|
||||||
(referenceLayer as any)._update();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
@ -164,13 +156,9 @@ export abstract class TbMapLayer<S extends MapLayerSettings> {
|
|||||||
}
|
}
|
||||||
return spec$.pipe(
|
return spec$.pipe(
|
||||||
map(spec => {
|
map(spec => {
|
||||||
const sourceSpec = (spec.sources['esri'] as VectorSourceSpecification);
|
return L.TB.MapLibreGL.mapLibreGLLayer({
|
||||||
const attribution = sourceSpec.attribution;
|
|
||||||
const gl = L.maplibreGL({
|
|
||||||
style: spec,
|
style: spec,
|
||||||
});
|
});
|
||||||
gl.options.attribution = attribution;
|
|
||||||
return gl;
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -758,6 +758,7 @@ export const mapProviderTranslationMap = new Map<MapProvider, string>(
|
|||||||
export enum ReferenceLayerType {
|
export enum ReferenceLayerType {
|
||||||
openstreetmap_hybrid = 'openstreetmap_hybrid',
|
openstreetmap_hybrid = 'openstreetmap_hybrid',
|
||||||
world_edition_hybrid = 'world_edition_hybrid',
|
world_edition_hybrid = 'world_edition_hybrid',
|
||||||
|
enhanced_contrast_hybrid = 'enhanced_contrast_hybrid'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const referenceLayerTypes = Object.keys(ReferenceLayerType) as ReferenceLayerType[];
|
export const referenceLayerTypes = Object.keys(ReferenceLayerType) as ReferenceLayerType[];
|
||||||
@ -765,7 +766,8 @@ export const referenceLayerTypes = Object.keys(ReferenceLayerType) as ReferenceL
|
|||||||
export const referenceLayerTypeTranslationMap = new Map<ReferenceLayerType, string>(
|
export const referenceLayerTypeTranslationMap = new Map<ReferenceLayerType, string>(
|
||||||
[
|
[
|
||||||
[ReferenceLayerType.openstreetmap_hybrid, 'widgets.maps.layer.reference.openstreetmap-hybrid'],
|
[ReferenceLayerType.openstreetmap_hybrid, 'widgets.maps.layer.reference.openstreetmap-hybrid'],
|
||||||
[ReferenceLayerType.world_edition_hybrid, 'widgets.maps.layer.reference.world-edition-hybrid']
|
[ReferenceLayerType.world_edition_hybrid, 'widgets.maps.layer.reference.world-edition-hybrid'],
|
||||||
|
[ReferenceLayerType.enhanced_contrast_hybrid, 'widgets.maps.layer.reference.enhanced-contrast-hybrid']
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -7910,7 +7910,8 @@
|
|||||||
"reference-layer": "Reference layer",
|
"reference-layer": "Reference layer",
|
||||||
"no-layer": "No layer",
|
"no-layer": "No layer",
|
||||||
"openstreetmap-hybrid": "OpenStreetMap Hybrid",
|
"openstreetmap-hybrid": "OpenStreetMap Hybrid",
|
||||||
"world-edition-hybrid": "World Edition Hybrid"
|
"world-edition-hybrid": "World Edition Hybrid",
|
||||||
|
"enhanced-contrast-hybrid": "Enhanced Contrast Hybrid"
|
||||||
},
|
},
|
||||||
"provider": {
|
"provider": {
|
||||||
"provider": "Provider",
|
"provider": "Provider",
|
||||||
|
|||||||
7937
ui-ngx/src/assets/map/enhanced_contrast_hybrid_reference_style.json
Normal file
7937
ui-ngx/src/assets/map/enhanced_contrast_hybrid_reference_style.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 8,
|
"version": 8,
|
||||||
"sprite": "https://cdn.arcgis.com/sharing/rest/content/items/f240fe360b434afc87dd989bf0c0b825/resources/sprites/sprite",
|
"sprite": "https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/resources/sprites/sprite",
|
||||||
"glyphs": "https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/resources/fonts/{fontstack}/{range}.pbf",
|
"glyphs": "https://basemaps.arcgis.com/arcgis/rest/services/OpenStreetMap_v2/VectorTileServer/resources/fonts/{fontstack}/{range}.pbf",
|
||||||
"sources": {
|
"sources": {
|
||||||
"esri": {
|
"esri": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": 8,
|
"version": 8,
|
||||||
"sprite": "https://cdn.arcgis.com/sharing/rest/content/items/30d6b8271e1849cd9c3042060001f425/resources/sprites/sprite",
|
"sprite": "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/sprites/sprite",
|
||||||
"glyphs": "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/fonts/{fontstack}/{range}.pbf",
|
"glyphs": "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/resources/fonts/{fontstack}/{range}.pbf",
|
||||||
"sources": {
|
"sources": {
|
||||||
"esri": {
|
"esri": {
|
||||||
|
|||||||
23
ui-ngx/src/typings/leaflet-extend-tb.d.ts
vendored
23
ui-ngx/src/typings/leaflet-extend-tb.d.ts
vendored
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
import { FormattedData } from '@shared/models/widget.models';
|
import { FormattedData } from '@shared/models/widget.models';
|
||||||
import L from 'leaflet';
|
import L from 'leaflet';
|
||||||
|
import { Map as MapLibreGLMap, MapOptions as MapLibreGLMapOptions } from 'maplibre-gl';
|
||||||
import { TbMapDatasource } from '@shared/models/widget/maps/map.models';
|
import { TbMapDatasource } from '@shared/models/widget/maps/map.models';
|
||||||
import { MatIconRegistry } from '@angular/material/icon';
|
import { MatIconRegistry } from '@angular/material/icon';
|
||||||
|
|
||||||
@ -61,7 +62,6 @@ declare module 'leaflet' {
|
|||||||
attributionPrefix?: string;
|
attributionPrefix?: string;
|
||||||
layer: Layer;
|
layer: Layer;
|
||||||
mini: Layer;
|
mini: Layer;
|
||||||
onAdd?: () => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LayersControlOptions extends SidebarPaneControlOptions {
|
interface LayersControlOptions extends SidebarPaneControlOptions {
|
||||||
@ -183,5 +183,26 @@ declare module 'leaflet' {
|
|||||||
namespace tileLayer {
|
namespace tileLayer {
|
||||||
function chinaProvider(type: string, options?: TileLayerOptions): TileLayer.ChinaProvider;
|
function chinaProvider(type: string, options?: TileLayerOptions): TileLayer.ChinaProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MapLibreGL {
|
||||||
|
|
||||||
|
interface LeafletMapLibreGLMapOptions extends L.InteractiveLayerOptions, Omit<MapLibreGLMapOptions, "container"> {
|
||||||
|
updateInterval?: number;
|
||||||
|
padding?: number;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapLibreGLLayer extends L.Layer {
|
||||||
|
constructor(options: LeafletMapLibreGLMapOptions);
|
||||||
|
getMapLibreGLMap(): MapLibreGLMap
|
||||||
|
getCanvas(): HTMLCanvasElement
|
||||||
|
getSize(): L.Point
|
||||||
|
getBounds(): L.LatLngBounds
|
||||||
|
getContainer(): HTMLDivElement
|
||||||
|
getPaneName(): string
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapLibreGLLayer(options: LeafletMapLibreGLMapOptions): MapLibreGLLayer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1971,21 +1971,16 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
|
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
|
||||||
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
|
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
|
||||||
|
|
||||||
"@maplibre/maplibre-gl-leaflet@^0.0.22":
|
"@maplibre/maplibre-gl-style-spec@^23.1.0":
|
||||||
version "0.0.22"
|
version "23.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-leaflet/-/maplibre-gl-leaflet-0.0.22.tgz#04c4d5b65f44be0962330f8b5a7cafc8c3bd2676"
|
resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-23.1.0.tgz#ad59731b0547ee0986ba4ccff699894dd60f0650"
|
||||||
integrity sha512-9p4DSPLUE5t0StXH/IcZw37/UL7Ekea4jcVdkSsb2jWI+sM3K7mYHLOnti/2wn+HqxG4jMVUHah7Xun3bs00AQ==
|
integrity sha512-R6/ihEuC5KRexmKIYkWqUv84Gm+/QwsOUgHyt1yy2XqCdGdLvlBWVWIIeTZWN4NGdwmY6xDzdSGU2R9oBLNg2w==
|
||||||
|
|
||||||
"@maplibre/maplibre-gl-style-spec@^20.3.1":
|
|
||||||
version "20.4.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.4.0.tgz#408339e051fb51e022b40af2235e0beb037937ea"
|
|
||||||
integrity sha512-AzBy3095fTFPjDjmWpR2w6HVRAZJ6hQZUCwk5Plz6EyfnfuQW1odeW5i2Ai47Y6TBA2hQnC+azscjBSALpaWgw==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@mapbox/jsonlint-lines-primitives" "~2.0.2"
|
"@mapbox/jsonlint-lines-primitives" "~2.0.2"
|
||||||
"@mapbox/unitbezier" "^0.0.1"
|
"@mapbox/unitbezier" "^0.0.1"
|
||||||
json-stringify-pretty-compact "^4.0.0"
|
json-stringify-pretty-compact "^4.0.0"
|
||||||
minimist "^1.2.8"
|
minimist "^1.2.8"
|
||||||
quickselect "^2.0.0"
|
quickselect "^3.0.0"
|
||||||
rw "^1.3.3"
|
rw "^1.3.3"
|
||||||
tinyqueue "^3.0.0"
|
tinyqueue "^3.0.0"
|
||||||
|
|
||||||
@ -2731,7 +2726,7 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca"
|
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca"
|
||||||
integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==
|
integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==
|
||||||
|
|
||||||
"@types/geojson@^7946.0.14":
|
"@types/geojson@^7946.0.16":
|
||||||
version "7946.0.16"
|
version "7946.0.16"
|
||||||
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a"
|
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a"
|
||||||
integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==
|
integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==
|
||||||
@ -4793,7 +4788,7 @@ domutils@^3.0.1:
|
|||||||
domelementtype "^2.3.0"
|
domelementtype "^2.3.0"
|
||||||
domhandler "^5.0.3"
|
domhandler "^5.0.3"
|
||||||
|
|
||||||
earcut@^3.0.0:
|
earcut@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.0.1.tgz#f60b3f671c5657cca9d3e131c5527c5dde00ef38"
|
resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.0.1.tgz#f60b3f671c5657cca9d3e131c5527c5dde00ef38"
|
||||||
integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==
|
integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==
|
||||||
@ -6933,10 +6928,10 @@ make-plural@^7.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-7.4.0.tgz#fa6990dd550dea4de6b20163f74e5ed83d8a8d6d"
|
resolved "https://registry.yarnpkg.com/make-plural/-/make-plural-7.4.0.tgz#fa6990dd550dea4de6b20163f74e5ed83d8a8d6d"
|
||||||
integrity sha512-4/gC9KVNTV6pvYg2gFeQYTW3mWaoJt7WZE5vrp1KnQDgW92JtYZnzmZT81oj/dUTqAIu0ufI2x3dkgu3bB1tYg==
|
integrity sha512-4/gC9KVNTV6pvYg2gFeQYTW3mWaoJt7WZE5vrp1KnQDgW92JtYZnzmZT81oj/dUTqAIu0ufI2x3dkgu3bB1tYg==
|
||||||
|
|
||||||
maplibre-gl@^4.7.1:
|
maplibre-gl@^5.2.0:
|
||||||
version "4.7.1"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-4.7.1.tgz#06a524438ee2aafbe8bcd91002a4e01468ea5486"
|
resolved "https://registry.yarnpkg.com/maplibre-gl/-/maplibre-gl-5.2.0.tgz#e3cdb66c82232cffbe149b032776484722caee4e"
|
||||||
integrity sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA==
|
integrity sha512-9zZKD0M80qtDsqBet+EDuAhoCeA/cnAuZAA0p3hcGKGbyjM/SH+R6wQvnBEgvJz9UhDynnkoKdUwhI+fUkHoXQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@mapbox/geojson-rewind" "^0.5.2"
|
"@mapbox/geojson-rewind" "^0.5.2"
|
||||||
"@mapbox/jsonlint-lines-primitives" "^2.0.2"
|
"@mapbox/jsonlint-lines-primitives" "^2.0.2"
|
||||||
@ -6945,14 +6940,14 @@ maplibre-gl@^4.7.1:
|
|||||||
"@mapbox/unitbezier" "^0.0.1"
|
"@mapbox/unitbezier" "^0.0.1"
|
||||||
"@mapbox/vector-tile" "^1.3.1"
|
"@mapbox/vector-tile" "^1.3.1"
|
||||||
"@mapbox/whoots-js" "^3.1.0"
|
"@mapbox/whoots-js" "^3.1.0"
|
||||||
"@maplibre/maplibre-gl-style-spec" "^20.3.1"
|
"@maplibre/maplibre-gl-style-spec" "^23.1.0"
|
||||||
"@types/geojson" "^7946.0.14"
|
"@types/geojson" "^7946.0.16"
|
||||||
"@types/geojson-vt" "3.2.5"
|
"@types/geojson-vt" "3.2.5"
|
||||||
"@types/mapbox__point-geometry" "^0.1.4"
|
"@types/mapbox__point-geometry" "^0.1.4"
|
||||||
"@types/mapbox__vector-tile" "^1.3.4"
|
"@types/mapbox__vector-tile" "^1.3.4"
|
||||||
"@types/pbf" "^3.0.5"
|
"@types/pbf" "^3.0.5"
|
||||||
"@types/supercluster" "^7.1.3"
|
"@types/supercluster" "^7.1.3"
|
||||||
earcut "^3.0.0"
|
earcut "^3.0.1"
|
||||||
geojson-vt "^4.0.2"
|
geojson-vt "^4.0.2"
|
||||||
gl-matrix "^3.4.3"
|
gl-matrix "^3.4.3"
|
||||||
global-prefix "^4.0.0"
|
global-prefix "^4.0.0"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user