Editable Polygons without proper typings
This commit is contained in:
parent
8750b26f1d
commit
423a491e80
@ -58,6 +58,7 @@
|
||||
"jstree-bootstrap-theme": "^1.0.1",
|
||||
"jszip": "^3.4.0",
|
||||
"leaflet": "^1.6.0",
|
||||
"leaflet-editable": "^1.2.0",
|
||||
"leaflet-polylinedecorator": "^1.6.0",
|
||||
"leaflet-providers": "^1.10.1",
|
||||
"leaflet.gridlayer.googlemutant": "0.10.0",
|
||||
|
||||
@ -43,6 +43,8 @@ import { createTooltip, parseArray, safeExecute } from '@home/components/widget/
|
||||
import { WidgetContext } from '@home/models/widget-component.models';
|
||||
import { DatasourceData } from '@shared/models/widget.models';
|
||||
import { deepClone, isDefinedAndNotNull } from '@core/utils';
|
||||
import {newArray} from "@angular/compiler/src/util";
|
||||
import {isArray} from "rxjs/internal-compatibility";
|
||||
|
||||
export default abstract class LeafletMap {
|
||||
|
||||
@ -168,6 +170,75 @@ export default abstract class LeafletMap {
|
||||
}
|
||||
}
|
||||
|
||||
addPolygonControl() {
|
||||
if (this.options.editablePolygon) {
|
||||
let mousePositionOnMap: L.LatLng[];
|
||||
let addPolygon: L.Control;
|
||||
this.map.on('mousemove', (e: L.LeafletMouseEvent) => {
|
||||
let latlng1 = e.latlng;
|
||||
let latlng2 = L.latLng(e.latlng.lat, e.latlng.lng + 10);
|
||||
let latlng3 = L.latLng(e.latlng.lat-10, e.latlng.lng);
|
||||
mousePositionOnMap = [latlng1,latlng2, latlng3 ];
|
||||
});
|
||||
const dragListener = (e: L.DragEndEvent) => {
|
||||
if (e.type === 'dragend' && mousePositionOnMap) {
|
||||
const icon = new L.Icon.Default();
|
||||
icon.options.shadowSize = [0, 0];
|
||||
const newPolygon = L.polygon(mousePositionOnMap).addTo(this.map);
|
||||
const datasourcesList = document.createElement('div');
|
||||
const customLatLng = {coordinates: this.convertToPolygonFormat(mousePositionOnMap)};
|
||||
this.datasources.forEach(ds => {
|
||||
const dsItem = document.createElement('p');
|
||||
dsItem.appendChild(document.createTextNode(ds.entityName));
|
||||
dsItem.setAttribute('style', 'font-size: 14px');
|
||||
dsItem.onclick = () => {
|
||||
const updatedEnttity = { ...ds, ...customLatLng };
|
||||
this.savePolygonLocation(updatedEnttity).subscribe(() => {
|
||||
this.map.removeLayer(newPolygon);
|
||||
this.deletePolygon(ds.entityName);
|
||||
// this.createPolygon(ds, this.datasources, this.options);
|
||||
});
|
||||
}
|
||||
datasourcesList.append(dsItem);
|
||||
});
|
||||
const deleteBtn = document.createElement('a');
|
||||
deleteBtn.appendChild(document.createTextNode('Delete position'));
|
||||
deleteBtn.setAttribute('color', 'red');
|
||||
deleteBtn.onclick = () => {
|
||||
this.map.removeLayer(newPolygon);
|
||||
}
|
||||
datasourcesList.append(deleteBtn);
|
||||
const popup = L.popup();
|
||||
popup.setContent(datasourcesList);
|
||||
newPolygon.bindPopup(popup).openPopup();
|
||||
}
|
||||
addPolygon.setPosition('topright')
|
||||
}
|
||||
L.Control.AddPolygon = L.Control.extend({
|
||||
onAdd() {
|
||||
const img = L.DomUtil.create('img') as any;
|
||||
img.src = `assets/add_polygon.svg`;
|
||||
img.style.width = '32px';
|
||||
img.style.height = '32px';
|
||||
img.title = 'Drag and drop to add Polygon';
|
||||
img.onclick = this.dragPolygonVertex;
|
||||
img.draggable = true;
|
||||
const draggableImg = new L.Draggable(img);
|
||||
draggableImg.enable();
|
||||
draggableImg.on('dragend', dragListener)
|
||||
return img;
|
||||
},
|
||||
onRemove() {
|
||||
},
|
||||
dragPolygonVertex: this.dragPolygonVertex
|
||||
} as any);
|
||||
L.control.addPolygon = (opts) => {
|
||||
return new L.Control.AddPolygon(opts);
|
||||
}
|
||||
addPolygon = L.control.addPolygon({ position: 'topright' }).addTo(this.map);
|
||||
}
|
||||
}
|
||||
|
||||
public setMap(map: L.Map) {
|
||||
this.map = map;
|
||||
if (this.options.useDefaultCenterPosition) {
|
||||
@ -178,6 +249,9 @@ export default abstract class LeafletMap {
|
||||
if (this.options.draggableMarker) {
|
||||
this.addMarkerControl();
|
||||
}
|
||||
if (this.options.editablePolygon) {
|
||||
this.addPolygonControl();
|
||||
}
|
||||
this.map$.next(this.map);
|
||||
}
|
||||
|
||||
@ -189,6 +263,10 @@ export default abstract class LeafletMap {
|
||||
return of(null);
|
||||
}
|
||||
|
||||
public savePolygonLocation(_e: FormattedData, coordinates?: Array<[number, number]>): Observable<any> {
|
||||
return of(null);
|
||||
}
|
||||
|
||||
createLatLng(lat: number, lng: number): L.LatLng {
|
||||
return L.latLng(lat, lng);
|
||||
}
|
||||
@ -255,9 +333,15 @@ export default abstract class LeafletMap {
|
||||
return L.latLng(lat, lng) as L.LatLng;
|
||||
}
|
||||
|
||||
convertPositionPolygon(expression: Array<[number, number]>): L.LatLngExpression[] {
|
||||
return expression.map((el) => {
|
||||
return el.length === 2 && !el.some(isNaN) ? el : null
|
||||
convertPositionPolygon(expression: Array<[number, number]> | Array<Array<[number, number]>>) {
|
||||
return (expression as Array<any>).map((el) => {
|
||||
if (el.length === 2 && !el.some(isNaN)) {
|
||||
return el;
|
||||
} else if (isArray(el) && el.length) {
|
||||
return this.convertPositionPolygon(el);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}).filter(el => !!el)
|
||||
}
|
||||
|
||||
@ -268,6 +352,26 @@ export default abstract class LeafletMap {
|
||||
}
|
||||
}
|
||||
|
||||
convertToPolygonFormat(points: Array<any>): Array<any> {
|
||||
if (points.length) {
|
||||
return points.map(point=> {
|
||||
if (point.length) {
|
||||
return this.convertToPolygonFormat(point);
|
||||
} else {
|
||||
return [point.lat, point.lng];
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
convertPolygonToCustomFormat(expression: Array<Array<any>>): object {
|
||||
return {
|
||||
[this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
|
||||
}
|
||||
}
|
||||
|
||||
updateData(data: DatasourceData[], formattedData: FormattedData[], drawRoutes: boolean, showPolygon: boolean) {
|
||||
this.ready$.subscribe(() => {
|
||||
if (drawRoutes) {
|
||||
@ -394,6 +498,15 @@ export default abstract class LeafletMap {
|
||||
}
|
||||
}
|
||||
|
||||
deletePolygon(key: string) {
|
||||
let polygon = this.polygons.get(key)?.leafletPoly;
|
||||
if (polygon) {
|
||||
this.map.removeLayer(polygon);
|
||||
this.polygons.delete(key);
|
||||
polygon = null;
|
||||
}
|
||||
}
|
||||
|
||||
updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) {
|
||||
this.map$.subscribe(map => {
|
||||
if (this.points) {
|
||||
@ -509,9 +622,14 @@ export default abstract class LeafletMap {
|
||||
});
|
||||
}
|
||||
|
||||
dragPolygonVertex = (e?, data = {} as FormattedData) => {
|
||||
if (e == undefined || (e.type !== 'editable:vertex:dragend' && e.type !== 'editable:vertex:deleted')) return;
|
||||
this.savePolygonLocation({ ...data, ...this.convertPolygonToCustomFormat(e.layer._latlngs) }).subscribe();
|
||||
}
|
||||
|
||||
createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
|
||||
this.ready$.subscribe(() => {
|
||||
const polygon = new Polygon(this.map, polyData, dataSources, settings);
|
||||
const polygon = new Polygon(this.map, polyData, dataSources, settings, this.dragPolygonVertex);
|
||||
if (updateBounds) {
|
||||
const bounds = polygon.leafletPoly.getBounds();
|
||||
this.fitBounds(bounds);
|
||||
|
||||
@ -34,6 +34,7 @@ export type PosFuncton = (origXPos, origYPos) => { x, y };
|
||||
|
||||
export type MapSettings = {
|
||||
draggableMarker: boolean;
|
||||
editablePolygon: boolean;
|
||||
initCallback?: () => any;
|
||||
posFunction: PosFuncton;
|
||||
defaultZoomLevel?: number;
|
||||
@ -140,6 +141,7 @@ export type PolygonSettings = {
|
||||
usePolygonColorFunction: boolean;
|
||||
polygonTooltipFunction: GenericFunction;
|
||||
polygonColorFunction?: GenericFunction;
|
||||
editablePolygon: boolean;
|
||||
}
|
||||
|
||||
export type PolylineSettings = {
|
||||
@ -268,6 +270,7 @@ export const defaultSettings: any = {
|
||||
credentials: '',
|
||||
markerClusteringSetting: null,
|
||||
draggableMarker: false,
|
||||
editablePolygon: false,
|
||||
fitMapBounds: true,
|
||||
mapPageSize: DEFAULT_MAP_PAGE_SIZE
|
||||
};
|
||||
|
||||
@ -79,6 +79,7 @@ export class MapWidgetController implements MapWidgetInterface {
|
||||
this.map = new MapClass(this.ctx, $element, this.settings);
|
||||
(this.ctx as any).mapInstance = this.map;
|
||||
this.map.saveMarkerLocation = this.setMarkerLocation;
|
||||
this.map.savePolygonLocation = this.savePolygonLocation;
|
||||
this.pageLink = {
|
||||
page: 0,
|
||||
pageSize: this.settings.mapPageSize,
|
||||
@ -239,6 +240,56 @@ export class MapWidgetController implements MapWidgetInterface {
|
||||
}
|
||||
}
|
||||
|
||||
savePolygonLocation = (e: FormattedData, coordinates?: Array<any>) => {
|
||||
const attributeService = this.ctx.$injector.get(AttributeService);
|
||||
|
||||
const entityId: EntityId = {
|
||||
entityType: e.$datasource.entityType,
|
||||
id: e.$datasource.entityId
|
||||
};
|
||||
const attributes = [];
|
||||
const timeseries = [];
|
||||
|
||||
const coordinatesProperties = this.settings.polygonKeyName;
|
||||
e.$datasource.dataKeys.forEach(key => {
|
||||
let value;
|
||||
if (coordinatesProperties == key.name) {
|
||||
value = {
|
||||
key: key.name,
|
||||
value: isDefined(coordinates) ? coordinates : e[key.name]
|
||||
};
|
||||
}
|
||||
if (value) {
|
||||
if (key.type === DataKeyType.attribute) {
|
||||
attributes.push(value)
|
||||
}
|
||||
if (key.type === DataKeyType.timeseries) {
|
||||
timeseries.push(value)
|
||||
}
|
||||
}
|
||||
});
|
||||
const observables: Observable<any>[] = [];
|
||||
if (timeseries.length) {
|
||||
observables.push(attributeService.saveEntityTimeseries(
|
||||
entityId,
|
||||
LatestTelemetry.LATEST_TELEMETRY,
|
||||
timeseries
|
||||
));
|
||||
}
|
||||
if (attributes.length) {
|
||||
observables.push(attributeService.saveEntityAttributes(
|
||||
entityId,
|
||||
AttributeScope.SERVER_SCOPE,
|
||||
attributes
|
||||
));
|
||||
}
|
||||
if (observables.length) {
|
||||
return forkJoin(observables);
|
||||
} else {
|
||||
return of(null);
|
||||
}
|
||||
}
|
||||
|
||||
initSettings(settings: UnitedMapSettings, isEditMap?: boolean): UnitedMapSettings {
|
||||
const functionParams = ['data', 'dsData', 'dsIndex'];
|
||||
this.provider = settings.provider || this.mapProvider;
|
||||
@ -270,6 +321,9 @@ export class MapWidgetController implements MapWidgetInterface {
|
||||
if (isEditMap && !settings.hasOwnProperty('draggableMarker')) {
|
||||
settings.draggableMarker = true;
|
||||
}
|
||||
if (isEditMap && !settings.hasOwnProperty('editablePolygon')) {
|
||||
settings.editablePolygon = true;
|
||||
}
|
||||
return { ...defaultSettings, ...settings, ...customOptions, }
|
||||
}
|
||||
|
||||
|
||||
@ -22,13 +22,13 @@
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.leaflet-div-icon,
|
||||
.tb-marker-label,
|
||||
.tb-marker-label:before {
|
||||
border: none;
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
//.leaflet-div-icon,
|
||||
//.tb-marker-label,
|
||||
//.tb-marker-label:before {
|
||||
// border: none;
|
||||
// background: none;
|
||||
// box-shadow: none;
|
||||
//}
|
||||
|
||||
.leaflet-container{
|
||||
background-color: white;
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import L, { LatLngExpression, LeafletMouseEvent } from 'leaflet';
|
||||
import L, { LatLngExpression, LeafletMouseEvent} from 'leaflet';
|
||||
import "leaflet-editable/src/Leaflet.Editable";
|
||||
import { createTooltip, parseWithTranslation, safeExecute } from './maps-utils';
|
||||
import { FormattedData, PolygonSettings } from './map-models';
|
||||
|
||||
@ -25,11 +26,10 @@ export class Polygon {
|
||||
data: FormattedData;
|
||||
dataSources: FormattedData[];
|
||||
|
||||
constructor(public map, polyData: FormattedData, dataSources: FormattedData[], private settings: PolygonSettings) {
|
||||
constructor(public map, polyData: FormattedData, dataSources: FormattedData[], private settings: PolygonSettings, onDragendListener?) {
|
||||
this.dataSources = dataSources;
|
||||
this.data = polyData;
|
||||
const polygonColor = this.getPolygonColor(settings);
|
||||
|
||||
this.leafletPoly = L.polygon(polyData[this.settings.polygonKeyName], {
|
||||
fill: true,
|
||||
fillColor: polygonColor,
|
||||
@ -38,6 +38,14 @@ export class Polygon {
|
||||
fillOpacity: settings.polygonOpacity,
|
||||
opacity: settings.polygonStrokeOpacity
|
||||
}).addTo(this.map);
|
||||
if (settings.editablePolygon) {
|
||||
this.leafletPoly.enableEdit(this.map);
|
||||
if (onDragendListener) {
|
||||
this.leafletPoly.on("editable:vertex:dragend", e => onDragendListener(e, this.data));
|
||||
this.leafletPoly.on("editable:vertex:deleted", e => onDragendListener(e, this.data));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (settings.showPolygonTooltip) {
|
||||
this.tooltip = createTooltip(this.leafletPoly, settings, polyData.$datasource);
|
||||
@ -64,7 +72,13 @@ export class Polygon {
|
||||
updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) {
|
||||
this.data = data;
|
||||
this.dataSources = dataSources;
|
||||
if (settings.editablePolygon) {
|
||||
this.leafletPoly.disableEdit();
|
||||
}
|
||||
this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]);
|
||||
if (settings.editablePolygon) {
|
||||
this.leafletPoly.enableEdit(this.map);
|
||||
}
|
||||
if (settings.showPolygonTooltip)
|
||||
this.updateTooltip(this.data);
|
||||
this.updatePolygonColor(settings);
|
||||
|
||||
@ -36,7 +36,7 @@ export class GoogleMap extends LeafletMap {
|
||||
super(ctx, $container, options);
|
||||
this.resource = ctx.$injector.get(ResourcesService);
|
||||
this.loadGoogle(() => {
|
||||
const map = L.map($container, {attributionControl: false}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
const map = L.map($container, {attributionControl: false, editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
(L.gridLayer as any).googleMutant({
|
||||
type: options?.gmDefaultMapType || 'roadmap'
|
||||
}).addTo(map);
|
||||
|
||||
@ -22,7 +22,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
|
||||
export class HEREMap extends LeafletMap {
|
||||
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
|
||||
super(ctx, $container, options);
|
||||
const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
const map = L.map($container, {editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
|
||||
tileLayer.addTo(map);
|
||||
super.setMap(map);
|
||||
|
||||
@ -24,7 +24,9 @@ import { WidgetContext } from '@home/models/widget-component.models';
|
||||
import { DataSet, DatasourceType, widgetType } from '@shared/models/widget.models';
|
||||
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
|
||||
import { WidgetSubscriptionOptions } from '@core/api/widget-api.models';
|
||||
import { isDefinedAndNotNull } from '@core/utils';
|
||||
import {isDefinedAndNotNull, isNumber} from '@core/utils';
|
||||
import "leaflet-editable/src/Leaflet.Editable";
|
||||
import {isArray} from "rxjs/internal-compatibility";
|
||||
|
||||
const maxZoom = 4;// ?
|
||||
|
||||
@ -203,7 +205,8 @@ export class ImageMap extends LeafletMap {
|
||||
center,
|
||||
zoom: 1,
|
||||
crs: L.CRS.Simple,
|
||||
attributionControl: false
|
||||
attributionControl: false,
|
||||
editable: !!this.options.editablePolygon
|
||||
});
|
||||
this.updateBounds(updateImage);
|
||||
}
|
||||
@ -221,14 +224,17 @@ export class ImageMap extends LeafletMap {
|
||||
expression.y * this.height);
|
||||
}
|
||||
|
||||
convertPositionPolygon(expression: Array<[number, number]>): L.LatLngExpression[] {
|
||||
return expression.map((el) => {
|
||||
convertPositionPolygon(expression: Array<[number, number]> | Array<Array<[number, number]>>) {
|
||||
return (expression as Array<any>).map((el) => {
|
||||
if (el.length === 2 && !el.some(isNaN)) {
|
||||
return this.pointToLatLng(
|
||||
el[0] * this.width,
|
||||
el[1] * this.height)
|
||||
}
|
||||
} else if (isArray(el) && el.length) {
|
||||
return this.convertPositionPolygon(el);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}).filter(el => !!el)
|
||||
}
|
||||
|
||||
@ -247,4 +253,25 @@ export class ImageMap extends LeafletMap {
|
||||
[this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, this.height)
|
||||
}
|
||||
}
|
||||
|
||||
convertToPolygonFormat(points: Array<any>): Array<any> {
|
||||
if (points.length) {
|
||||
return points.map(point=> {
|
||||
if (point.length) {
|
||||
return this.convertToPolygonFormat(point);
|
||||
} else {
|
||||
let pos = this.latLngToPoint(point);
|
||||
return [calculateNewPointCoordinate(pos.x, this.width), calculateNewPointCoordinate(pos.y, this.height)];
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
convertPolygonToCustomFormat(expression: Array<Array<any>>): object {
|
||||
return {
|
||||
[this.options.polygonKeyName] : this.convertToPolygonFormat(expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
|
||||
export class OpenStreetMap extends LeafletMap {
|
||||
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
|
||||
super(ctx, $container, options);
|
||||
const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
const map = new L.Map($container, {editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
let tileLayer;
|
||||
if (options.useCustomProvider)
|
||||
tileLayer = L.tileLayer(options.customProviderTileUrl);
|
||||
|
||||
@ -24,7 +24,7 @@ export class TencentMap extends LeafletMap {
|
||||
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
|
||||
super(ctx, $container, options);
|
||||
const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0';
|
||||
const map = L.map($container).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
const map = L.map($container, {editable: !!options.editablePolygon}).setView(options?.defaultCenterPosition, options?.defaultZoomLevel);
|
||||
const txLayer = L.tileLayer(txUrl, {
|
||||
subdomains: '0123',
|
||||
tms: true,
|
||||
|
||||
3
ui-ngx/src/assets/add_polygon.svg
Normal file
3
ui-ngx/src/assets/add_polygon.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
|
||||
<polygon points="2,46 46,46 24,2" style="fill:transparent;stroke:black;stroke-width:2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 182 B |
3
ui-ngx/src/typings/add-marker.d.ts
vendored
3
ui-ngx/src/typings/add-marker.d.ts
vendored
@ -20,9 +20,12 @@ declare module 'leaflet' {
|
||||
|
||||
namespace Control {
|
||||
class AddMarker extends L.Control { }
|
||||
class AddPolygon extends L.Control { }
|
||||
}
|
||||
|
||||
namespace control {
|
||||
function addMarker(options): Control.AddMarker;
|
||||
function addPolygon(options): Control.AddPolygon;
|
||||
}
|
||||
|
||||
}
|
||||
272
ui-ngx/src/typings/leadflet-editable.d.ts
vendored
Normal file
272
ui-ngx/src/typings/leadflet-editable.d.ts
vendored
Normal file
@ -0,0 +1,272 @@
|
||||
///
|
||||
/// Copyright © 2016-2020 The Thingsboard Authors
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import * as Leaflet from 'leaflet';
|
||||
|
||||
declare module 'leaflet' {
|
||||
|
||||
/**
|
||||
* Make geometries editable in Leaflet.
|
||||
*
|
||||
* This is not a plug and play UI, and will not. This is a minimal, lightweight, and fully extendable API to
|
||||
* control editing of geometries. So you can easily build your own UI with your own needs and choices.
|
||||
*/
|
||||
interface EditableStatic {
|
||||
new (map: Map, options: EditOptions): Editable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to pass to L.Editable when instanciating.
|
||||
*/
|
||||
interface EditOptions extends Leaflet.MapOptions{
|
||||
/**
|
||||
* Class to be used when creating a new Polyline.
|
||||
*/
|
||||
polylineClass?: object;
|
||||
|
||||
/**
|
||||
* Class to be used when creating a new Polygon.
|
||||
*/
|
||||
polygonClass?: object;
|
||||
|
||||
/**
|
||||
* Class to be used when creating a new Marker.
|
||||
*/
|
||||
markerClass?: object;
|
||||
|
||||
/**
|
||||
* CSS class to be added to the map container while drawing.
|
||||
*/
|
||||
drawingCSSClass?: string;
|
||||
|
||||
/**
|
||||
* Layer used to store edit tools (vertex, line guide…).
|
||||
*/
|
||||
editLayer?: LayerGroup<Leaflet.Layer>;
|
||||
|
||||
/**
|
||||
* Default layer used to store drawn features (marker, polyline…).
|
||||
*/
|
||||
featuresLayer?: LayerGroup<Polyline|Polygon|Marker>;
|
||||
|
||||
/**
|
||||
* Class to be used as vertex, for path editing.
|
||||
*/
|
||||
vertexMarkerClass?: object;
|
||||
|
||||
/**
|
||||
* Class to be used as middle vertex, pulled by the user to create a new point in the middle of a path.
|
||||
*/
|
||||
middleMarkerClass?: object;
|
||||
|
||||
/**
|
||||
* Class to be used as Polyline editor.
|
||||
*/
|
||||
polylineEditorClass?: object;
|
||||
|
||||
/**
|
||||
* Class to be used as Polygon editor.
|
||||
*/
|
||||
polygonEditorClass?: object;
|
||||
|
||||
/**
|
||||
* Class to be used as Marker editor.
|
||||
*/
|
||||
markerEditorClass?: object;
|
||||
|
||||
/**
|
||||
* Options to be passed to the line guides.
|
||||
*/
|
||||
lineGuideOptions?: object;
|
||||
|
||||
/**
|
||||
* Set this to true if you don't want middle markers.
|
||||
*/
|
||||
skipMiddleMarkers?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make geometries editable in Leaflet.
|
||||
*
|
||||
* This is not a plug and play UI, and will not. This is a minimal, lightweight, and fully extendable API to
|
||||
* control editing of geometries. So you can easily build your own UI with your own needs and choices.
|
||||
*/
|
||||
interface Editable extends Leaflet.Evented {
|
||||
/**
|
||||
* Options to pass to L.Editable when instanciating.
|
||||
*/
|
||||
options: EditOptions;
|
||||
|
||||
currentPolygon: Polyline|Polygon|Marker;
|
||||
|
||||
/**
|
||||
* Start drawing a polyline. If latlng is given, a first point will be added. In any case, continuing on user
|
||||
* click. If options is given, it will be passed to the polyline class constructor.
|
||||
*/
|
||||
startPolyline(latLng?: LatLng, options?: PolylineOptions): Polyline;
|
||||
|
||||
/**
|
||||
* Start drawing a polygon. If latlng is given, a first point will be added. In any case, continuing on user
|
||||
* click. If options is given, it will be passed to the polygon class constructor.
|
||||
*/
|
||||
startPolygon(latLng?: LatLng, options?: PolylineOptions): Polygon;
|
||||
|
||||
/**
|
||||
* Start adding a marker. If latlng is given, the marker will be shown first at this point. In any case, it
|
||||
* will follow the user mouse, and will have a final latlng on next click (or touch). If options is given,
|
||||
* it will be passed to the marker class constructor.
|
||||
*/
|
||||
startMarker(latLng?: LatLng, options?: MarkerOptions): Marker;
|
||||
|
||||
/**
|
||||
* When you need to stop any ongoing drawing, without needing to know which editor is active.
|
||||
*/
|
||||
stopDrawing(): void;
|
||||
|
||||
/**
|
||||
* When you need to commit any ongoing drawing, without needing to know which editor is active.
|
||||
*/
|
||||
commitDrawing(): void;
|
||||
}
|
||||
|
||||
let Editable: EditableStatic;
|
||||
|
||||
/**
|
||||
* EditableMixin is included to L.Polyline, L.Polygon and L.Marker. It adds the following methods to them.
|
||||
*
|
||||
* When editing is enabled, the editor is accessible on the instance with the editor property.
|
||||
*/
|
||||
interface EditableMixin {
|
||||
/**
|
||||
* Enable editing, by creating an editor if not existing, and then calling enable on it.
|
||||
*/
|
||||
enableEdit(map: L.Map): any;
|
||||
|
||||
/**
|
||||
* Disable editing, also remove the editor property reference.
|
||||
*/
|
||||
disableEdit(): void;
|
||||
|
||||
/**
|
||||
* Enable or disable editing, according to current status.
|
||||
*/
|
||||
toggleEdit(): void;
|
||||
|
||||
/**
|
||||
* Return true if current instance has an editor attached, and this editor is enabled.
|
||||
*/
|
||||
editEnabled(): boolean;
|
||||
}
|
||||
|
||||
interface Map {
|
||||
/**
|
||||
* Whether to create a L.Editable instance at map init or not.
|
||||
*/
|
||||
editable: boolean;
|
||||
|
||||
/**
|
||||
* Options to pass to L.Editable when instanciating.
|
||||
*/
|
||||
editOptions: EditOptions;
|
||||
|
||||
/**
|
||||
* L.Editable plugin instance.
|
||||
*/
|
||||
editTools: Editable;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-empty-interface
|
||||
interface Polyline extends EditableMixin {}
|
||||
|
||||
namespace Map {
|
||||
interface MapOptions {
|
||||
/**
|
||||
* Whether to create a L.Editable instance at map init or not.
|
||||
*/
|
||||
editable?: boolean;
|
||||
|
||||
/**
|
||||
* Options to pass to L.Editable when instanciating.
|
||||
*/
|
||||
editOptions?: EditOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When editing a feature (marker, polyline…), an editor is attached to it. This editor basically knows
|
||||
* how to handle the edition.
|
||||
*/
|
||||
interface BaseEditor {
|
||||
/**
|
||||
* Set up the drawing tools for the feature to be editable.
|
||||
*/
|
||||
enable(): MarkerEditor|PolylineEditor|PolygonEditor;
|
||||
|
||||
/**
|
||||
* Remove editing tools.
|
||||
*/
|
||||
disable(): MarkerEditor|PolylineEditor|PolygonEditor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from L.Editable.BaseEditor.
|
||||
* Inherited by L.Editable.PolylineEditor and L.Editable.PolygonEditor.
|
||||
*/
|
||||
interface PathEditor extends BaseEditor {
|
||||
/**
|
||||
* Rebuild edit elements (vertex, middlemarker, etc.).
|
||||
*/
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from L.Editable.PathEditor.
|
||||
*/
|
||||
interface PolylineEditor extends PathEditor {
|
||||
/**
|
||||
* Set up drawing tools to continue the line forward.
|
||||
*/
|
||||
continueForward(): void;
|
||||
|
||||
/**
|
||||
* Set up drawing tools to continue the line backward.
|
||||
*/
|
||||
continueBackward(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from L.Editable.PathEditor.
|
||||
*/
|
||||
interface PolygonEditor extends PathEditor {
|
||||
/**
|
||||
* Set up drawing tools for creating a new hole on the polygon. If the latlng param is given, a first
|
||||
* point is created.
|
||||
*/
|
||||
newHole(latlng: LatLng): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit from L.Editable.BaseEditor.
|
||||
*/
|
||||
// tslint:disable-next-line:no-empty-interface
|
||||
interface MarkerEditor extends BaseEditor {}
|
||||
|
||||
interface Marker extends EditableMixin, MarkerEditor {}
|
||||
|
||||
interface Polyline extends EditableMixin, PolylineEditor {}
|
||||
|
||||
interface Polygon extends EditableMixin, PolygonEditor {}
|
||||
}
|
||||
@ -20,7 +20,8 @@
|
||||
"src/typings/jquery.flot.typings.d.ts",
|
||||
"src/typings/jquery.jstree.typings.d.ts",
|
||||
"src/typings/split.js.typings.d.ts",
|
||||
"src/typings/add-marker.d.ts"
|
||||
"src/typings/add-marker.d.ts",
|
||||
"src/typings/leaflet-editable.d.ts"
|
||||
],
|
||||
"paths": {
|
||||
"@app/*": ["src/app/*"],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user