Editable Polygons without proper typings

This commit is contained in:
Mrkartoshka 2020-08-10 22:52:26 +03:00
parent 8750b26f1d
commit 423a491e80
15 changed files with 524 additions and 28 deletions

View File

@ -58,6 +58,7 @@
"jstree-bootstrap-theme": "^1.0.1", "jstree-bootstrap-theme": "^1.0.1",
"jszip": "^3.4.0", "jszip": "^3.4.0",
"leaflet": "^1.6.0", "leaflet": "^1.6.0",
"leaflet-editable": "^1.2.0",
"leaflet-polylinedecorator": "^1.6.0", "leaflet-polylinedecorator": "^1.6.0",
"leaflet-providers": "^1.10.1", "leaflet-providers": "^1.10.1",
"leaflet.gridlayer.googlemutant": "0.10.0", "leaflet.gridlayer.googlemutant": "0.10.0",

View File

@ -43,6 +43,8 @@ import { createTooltip, parseArray, safeExecute } from '@home/components/widget/
import { WidgetContext } from '@home/models/widget-component.models'; import { WidgetContext } from '@home/models/widget-component.models';
import { DatasourceData } from '@shared/models/widget.models'; import { DatasourceData } from '@shared/models/widget.models';
import { deepClone, isDefinedAndNotNull } from '@core/utils'; import { deepClone, isDefinedAndNotNull } from '@core/utils';
import {newArray} from "@angular/compiler/src/util";
import {isArray} from "rxjs/internal-compatibility";
export default abstract class LeafletMap { 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) { public setMap(map: L.Map) {
this.map = map; this.map = map;
if (this.options.useDefaultCenterPosition) { if (this.options.useDefaultCenterPosition) {
@ -178,6 +249,9 @@ export default abstract class LeafletMap {
if (this.options.draggableMarker) { if (this.options.draggableMarker) {
this.addMarkerControl(); this.addMarkerControl();
} }
if (this.options.editablePolygon) {
this.addPolygonControl();
}
this.map$.next(this.map); this.map$.next(this.map);
} }
@ -189,6 +263,10 @@ export default abstract class LeafletMap {
return of(null); return of(null);
} }
public savePolygonLocation(_e: FormattedData, coordinates?: Array<[number, number]>): Observable<any> {
return of(null);
}
createLatLng(lat: number, lng: number): L.LatLng { createLatLng(lat: number, lng: number): L.LatLng {
return L.latLng(lat, lng); return L.latLng(lat, lng);
} }
@ -255,9 +333,15 @@ export default abstract class LeafletMap {
return L.latLng(lat, lng) as L.LatLng; return L.latLng(lat, lng) as L.LatLng;
} }
convertPositionPolygon(expression: Array<[number, number]>): L.LatLngExpression[] { convertPositionPolygon(expression: Array<[number, number]> | Array<Array<[number, number]>>) {
return expression.map((el) => { return (expression as Array<any>).map((el) => {
return el.length === 2 && !el.some(isNaN) ? el : null 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) }).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) { updateData(data: DatasourceData[], formattedData: FormattedData[], drawRoutes: boolean, showPolygon: boolean) {
this.ready$.subscribe(() => { this.ready$.subscribe(() => {
if (drawRoutes) { 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) { updatePoints(pointsData: FormattedData[], getTooltip: (point: FormattedData, setTooltip?: boolean) => string) {
this.map$.subscribe(map => { this.map$.subscribe(map => {
if (this.points) { 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) { createPolygon(polyData: FormattedData, dataSources: FormattedData[], settings: PolygonSettings, updateBounds = true) {
this.ready$.subscribe(() => { 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) { if (updateBounds) {
const bounds = polygon.leafletPoly.getBounds(); const bounds = polygon.leafletPoly.getBounds();
this.fitBounds(bounds); this.fitBounds(bounds);

View File

@ -34,6 +34,7 @@ export type PosFuncton = (origXPos, origYPos) => { x, y };
export type MapSettings = { export type MapSettings = {
draggableMarker: boolean; draggableMarker: boolean;
editablePolygon: boolean;
initCallback?: () => any; initCallback?: () => any;
posFunction: PosFuncton; posFunction: PosFuncton;
defaultZoomLevel?: number; defaultZoomLevel?: number;
@ -140,6 +141,7 @@ export type PolygonSettings = {
usePolygonColorFunction: boolean; usePolygonColorFunction: boolean;
polygonTooltipFunction: GenericFunction; polygonTooltipFunction: GenericFunction;
polygonColorFunction?: GenericFunction; polygonColorFunction?: GenericFunction;
editablePolygon: boolean;
} }
export type PolylineSettings = { export type PolylineSettings = {
@ -268,6 +270,7 @@ export const defaultSettings: any = {
credentials: '', credentials: '',
markerClusteringSetting: null, markerClusteringSetting: null,
draggableMarker: false, draggableMarker: false,
editablePolygon: false,
fitMapBounds: true, fitMapBounds: true,
mapPageSize: DEFAULT_MAP_PAGE_SIZE mapPageSize: DEFAULT_MAP_PAGE_SIZE
}; };

View File

@ -79,6 +79,7 @@ export class MapWidgetController implements MapWidgetInterface {
this.map = new MapClass(this.ctx, $element, this.settings); this.map = new MapClass(this.ctx, $element, this.settings);
(this.ctx as any).mapInstance = this.map; (this.ctx as any).mapInstance = this.map;
this.map.saveMarkerLocation = this.setMarkerLocation; this.map.saveMarkerLocation = this.setMarkerLocation;
this.map.savePolygonLocation = this.savePolygonLocation;
this.pageLink = { this.pageLink = {
page: 0, page: 0,
pageSize: this.settings.mapPageSize, 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 { initSettings(settings: UnitedMapSettings, isEditMap?: boolean): UnitedMapSettings {
const functionParams = ['data', 'dsData', 'dsIndex']; const functionParams = ['data', 'dsData', 'dsIndex'];
this.provider = settings.provider || this.mapProvider; this.provider = settings.provider || this.mapProvider;
@ -270,6 +321,9 @@ export class MapWidgetController implements MapWidgetInterface {
if (isEditMap && !settings.hasOwnProperty('draggableMarker')) { if (isEditMap && !settings.hasOwnProperty('draggableMarker')) {
settings.draggableMarker = true; settings.draggableMarker = true;
} }
if (isEditMap && !settings.hasOwnProperty('editablePolygon')) {
settings.editablePolygon = true;
}
return { ...defaultSettings, ...settings, ...customOptions, } return { ...defaultSettings, ...settings, ...customOptions, }
} }

View File

@ -22,13 +22,13 @@
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.leaflet-div-icon, //.leaflet-div-icon,
.tb-marker-label, //.tb-marker-label,
.tb-marker-label:before { //.tb-marker-label:before {
border: none; // border: none;
background: none; // background: none;
box-shadow: none; // box-shadow: none;
} //}
.leaflet-container{ .leaflet-container{
background-color: white; background-color: white;

View File

@ -14,7 +14,8 @@
/// limitations under the License. /// 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 { createTooltip, parseWithTranslation, safeExecute } from './maps-utils';
import { FormattedData, PolygonSettings } from './map-models'; import { FormattedData, PolygonSettings } from './map-models';
@ -25,11 +26,10 @@ export class Polygon {
data: FormattedData; data: FormattedData;
dataSources: 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.dataSources = dataSources;
this.data = polyData; this.data = polyData;
const polygonColor = this.getPolygonColor(settings); const polygonColor = this.getPolygonColor(settings);
this.leafletPoly = L.polygon(polyData[this.settings.polygonKeyName], { this.leafletPoly = L.polygon(polyData[this.settings.polygonKeyName], {
fill: true, fill: true,
fillColor: polygonColor, fillColor: polygonColor,
@ -38,6 +38,14 @@ export class Polygon {
fillOpacity: settings.polygonOpacity, fillOpacity: settings.polygonOpacity,
opacity: settings.polygonStrokeOpacity opacity: settings.polygonStrokeOpacity
}).addTo(this.map); }).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) { if (settings.showPolygonTooltip) {
this.tooltip = createTooltip(this.leafletPoly, settings, polyData.$datasource); this.tooltip = createTooltip(this.leafletPoly, settings, polyData.$datasource);
@ -64,7 +72,13 @@ export class Polygon {
updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) { updatePolygon(data: FormattedData, dataSources: FormattedData[], settings: PolygonSettings) {
this.data = data; this.data = data;
this.dataSources = dataSources; this.dataSources = dataSources;
if (settings.editablePolygon) {
this.leafletPoly.disableEdit();
}
this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]); this.leafletPoly.setLatLngs(data[this.settings.polygonKeyName]);
if (settings.editablePolygon) {
this.leafletPoly.enableEdit(this.map);
}
if (settings.showPolygonTooltip) if (settings.showPolygonTooltip)
this.updateTooltip(this.data); this.updateTooltip(this.data);
this.updatePolygonColor(settings); this.updatePolygonColor(settings);

View File

@ -36,7 +36,7 @@ export class GoogleMap extends LeafletMap {
super(ctx, $container, options); super(ctx, $container, options);
this.resource = ctx.$injector.get(ResourcesService); this.resource = ctx.$injector.get(ResourcesService);
this.loadGoogle(() => { 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({ (L.gridLayer as any).googleMutant({
type: options?.gmDefaultMapType || 'roadmap' type: options?.gmDefaultMapType || 'roadmap'
}).addTo(map); }).addTo(map);

View File

@ -22,7 +22,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
export class HEREMap extends LeafletMap { export class HEREMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
super(ctx, $container, options); 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); const tileLayer = (L.tileLayer as any).provider(options.mapProviderHere || 'HERE.normalDay', options.credentials);
tileLayer.addTo(map); tileLayer.addTo(map);
super.setMap(map); super.setMap(map);

View File

@ -24,7 +24,9 @@ import { WidgetContext } from '@home/models/widget-component.models';
import { DataSet, DatasourceType, widgetType } from '@shared/models/widget.models'; import { DataSet, DatasourceType, widgetType } from '@shared/models/widget.models';
import { DataKeyType } from '@shared/models/telemetry/telemetry.models'; import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
import { WidgetSubscriptionOptions } from '@core/api/widget-api.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;// ? const maxZoom = 4;// ?
@ -203,7 +205,8 @@ export class ImageMap extends LeafletMap {
center, center,
zoom: 1, zoom: 1,
crs: L.CRS.Simple, crs: L.CRS.Simple,
attributionControl: false attributionControl: false,
editable: !!this.options.editablePolygon
}); });
this.updateBounds(updateImage); this.updateBounds(updateImage);
} }
@ -221,14 +224,17 @@ export class ImageMap extends LeafletMap {
expression.y * this.height); expression.y * this.height);
} }
convertPositionPolygon(expression: Array<[number, number]>): L.LatLngExpression[] { convertPositionPolygon(expression: Array<[number, number]> | Array<Array<[number, number]>>) {
return expression.map((el) => { return (expression as Array<any>).map((el) => {
if (el.length === 2 && !el.some(isNaN)) { if (el.length === 2 && !el.some(isNaN)) {
return this.pointToLatLng( return this.pointToLatLng(
el[0] * this.width, el[0] * this.width,
el[1] * this.height) el[1] * this.height)
} } else if (isArray(el) && el.length) {
return this.convertPositionPolygon(el);
} else {
return null; return null;
}
}).filter(el => !!el) }).filter(el => !!el)
} }
@ -247,4 +253,25 @@ export class ImageMap extends LeafletMap {
[this.options.yPosKeyName]: calculateNewPointCoordinate(point.y, this.height) [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)
}
}
} }

View File

@ -22,7 +22,7 @@ import { WidgetContext } from '@home/models/widget-component.models';
export class OpenStreetMap extends LeafletMap { export class OpenStreetMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
super(ctx, $container, options); 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; let tileLayer;
if (options.useCustomProvider) if (options.useCustomProvider)
tileLayer = L.tileLayer(options.customProviderTileUrl); tileLayer = L.tileLayer(options.customProviderTileUrl);

View File

@ -24,7 +24,7 @@ export class TencentMap extends LeafletMap {
constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) { constructor(ctx: WidgetContext, $container, options: UnitedMapSettings) {
super(ctx, $container, options); super(ctx, $container, options);
const txUrl = 'http://rt{s}.map.gtimg.com/realtimerender?z={z}&x={x}&y={y}&type=vector&style=0'; 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, { const txLayer = L.tileLayer(txUrl, {
subdomains: '0123', subdomains: '0123',
tms: true, tms: true,

View 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

View File

@ -20,9 +20,12 @@ declare module 'leaflet' {
namespace Control { namespace Control {
class AddMarker extends L.Control { } class AddMarker extends L.Control { }
class AddPolygon extends L.Control { }
} }
namespace control { namespace control {
function addMarker(options): Control.AddMarker; function addMarker(options): Control.AddMarker;
function addPolygon(options): Control.AddPolygon;
} }
} }

View 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 {}
}

View File

@ -20,7 +20,8 @@
"src/typings/jquery.flot.typings.d.ts", "src/typings/jquery.flot.typings.d.ts",
"src/typings/jquery.jstree.typings.d.ts", "src/typings/jquery.jstree.typings.d.ts",
"src/typings/split.js.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": { "paths": {
"@app/*": ["src/app/*"], "@app/*": ["src/app/*"],