@hpcc-js/map 3.4.10 → 3.4.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +43 -43
- package/README.md +88 -88
- package/TopoJSON/BR.json +122 -122
- package/TopoJSON/GB_idx.json +1 -1
- package/TopoJSON/IE_idx.json +1 -1
- package/TopoJSON/ND_idx.json +1 -1
- package/TopoJSON/countries.json +257 -257
- package/TopoJSON/us-counties.json +16550 -16550
- package/TopoJSON/us-states.json +458 -458
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +7 -7
- package/src/CanvasPinLayer.ts +99 -99
- package/src/CanvasPins.ts +397 -397
- package/src/Choropleth.css +27 -27
- package/src/Choropleth.ts +203 -203
- package/src/ChoroplethContinents.ts +13 -13
- package/src/ChoroplethCounties.ts +111 -111
- package/src/ChoroplethCountries.ts +100 -100
- package/src/ChoroplethStates.ts +103 -103
- package/src/ChoroplethStatesHeat.ts +8 -8
- package/src/GMap.css +16 -16
- package/src/GMap.ts +880 -880
- package/src/GMapCounties.ts +93 -93
- package/src/GMapGraph.ts +61 -61
- package/src/GMapHeat.ts +27 -27
- package/src/GMapLayered.ts +94 -94
- package/src/GMapPin.ts +115 -115
- package/src/GMapPinLine.ts +138 -138
- package/src/GeoHash.css +15 -15
- package/src/GeoHash.ts +139 -139
- package/src/Graph.css +10 -10
- package/src/Graph.ts +98 -98
- package/src/Graticule.css +13 -13
- package/src/Graticule.ts +97 -97
- package/src/Heat.css +2 -2
- package/src/Heat.ts +87 -87
- package/src/IChoropleth.ts +8 -8
- package/src/Layer.ts +99 -99
- package/src/Layered.css +19 -19
- package/src/Layered.ts +206 -206
- package/src/Lines.css +9 -9
- package/src/Lines.ts +78 -78
- package/src/OpenStreet.css +15 -15
- package/src/OpenStreet.ts +126 -126
- package/src/Pins.css +18 -18
- package/src/Pins.ts +350 -350
- package/src/Projection.ts +42 -42
- package/src/TestHeatMap.ts +8 -8
- package/src/TopoJSONChoropleth.ts +125 -125
- package/src/Utility.ts +484 -484
- package/src/__package__.ts +3 -3
- package/src/index.ts +33 -33
- package/src/leaflet/AlbersPR.ts +48 -48
- package/src/leaflet/Blank.ts +9 -9
- package/src/leaflet/Circles.ts +139 -139
- package/src/leaflet/ClusterCircles.css +26 -26
- package/src/leaflet/ClusterCircles.ts +88 -88
- package/src/leaflet/Countries.ts +43 -43
- package/src/leaflet/DrawLayer.ts +167 -167
- package/src/leaflet/FeatureLayer.ts +138 -138
- package/src/leaflet/GMap.ts +44 -44
- package/src/leaflet/HeatLayer.ts +77 -77
- package/src/leaflet/Icons.ts +60 -60
- package/src/leaflet/Leaflet.css +3 -3
- package/src/leaflet/Leaflet.ts +239 -239
- package/src/leaflet/MapBox.ts +35 -35
- package/src/leaflet/Markers.ts +109 -109
- package/src/leaflet/OpenStreet.ts +27 -27
- package/src/leaflet/Path.ts +138 -138
- package/src/leaflet/Pins.ts +73 -73
- package/src/leaflet/Polygons.ts +113 -113
- package/src/leaflet/Region.ts +138 -138
- package/src/leaflet/Text.ts +99 -99
- package/src/leaflet/TileLayer.ts +81 -81
- package/src/leaflet/TopoJSON.ts +146 -146
- package/src/leaflet/US.ts +15 -15
- package/src/leaflet/USCounties.ts +43 -43
- package/src/leaflet/USStates.ts +41 -41
- package/src/leaflet/World.css +3 -3
- package/src/leaflet/World.ts +172 -172
- package/src/leaflet/index.ts +18 -18
- package/src/leaflet/leaflet-shim.ts +18 -18
- package/src/leaflet/plugins/BeautifyIcon.css +44 -44
- package/src/leaflet/plugins/BeautifyIcon.ts +190 -190
- package/src/leaflet/plugins/BeutifyIcon.licence +20 -20
- package/src/leaflet/plugins/D3SvgOverlay.css +3 -3
- package/src/leaflet/plugins/D3SvgOverlay.licence +20 -20
- package/src/leaflet/plugins/D3SvgOverlay.ts +175 -175
- package/src/leaflet/plugins/HeatLayer.license +21 -21
- package/src/leaflet/plugins/HeatLayer.ts +224 -224
- package/src/leaflet/plugins/Leaflet.GoogleMutant.ts +424 -424
- package/src/leaflet/plugins/lru_map.ts +352 -352
- package/src/test.ts +114 -114
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
import { extent as d3Extent, Palette } from "@hpcc-js/common";
|
|
2
|
-
import { DivIcon, Map, Marker, Point } from "./leaflet-shim.ts";
|
|
3
|
-
import { hsl as d3Hsl } from "d3-color";
|
|
4
|
-
import { format as d3Format } from "d3-format";
|
|
5
|
-
import { FeatureLayer } from "./FeatureLayer.ts";
|
|
6
|
-
|
|
7
|
-
import "../../src/leaflet/ClusterCircles.css";
|
|
8
|
-
|
|
9
|
-
export class ClusterCircles extends FeatureLayer {
|
|
10
|
-
|
|
11
|
-
_palette;
|
|
12
|
-
|
|
13
|
-
protected createIcon(childCount: number, backColor: string, format: (_: any) => any) {
|
|
14
|
-
const borderColor = d3Hsl(backColor);
|
|
15
|
-
borderColor.opacity = 0.5;
|
|
16
|
-
return new DivIcon({
|
|
17
|
-
className: "cluster-circle",
|
|
18
|
-
iconSize: new Point(40, 40),
|
|
19
|
-
html: `<div style='opacity:${this.opacity()};background-color:${borderColor.toString()}'><div style='background-color:${backColor}'><span style='color:${Palette.textColor(backColor)}'>${format(childCount)}</span></div></div>`
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
layerUpdate(map: Map) {
|
|
24
|
-
super.layerUpdate(map);
|
|
25
|
-
this._palette = this._palette.switch(this.paletteID());
|
|
26
|
-
if (this.useClonedPalette()) {
|
|
27
|
-
this._palette = this._palette.cloneNotExists(this.paletteID() + "_" + this.id());
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const latFunc = this.cellFunc(this.latitudeColumn(), 0);
|
|
31
|
-
const longFunc = this.cellFunc(this.longitudeColumn(), 0);
|
|
32
|
-
const latLongFunc = (row): [number, number] => [+latFunc(row), +longFunc(row)];
|
|
33
|
-
const weightFunc = this.cellFunc(this.weightColumn(), 0);
|
|
34
|
-
|
|
35
|
-
const data: any[][] = this.data();
|
|
36
|
-
|
|
37
|
-
const extent = d3Extent(data, weightFunc);
|
|
38
|
-
|
|
39
|
-
const format = this.weightFormat() ? d3Format(this.weightFormat()) : _ => _;
|
|
40
|
-
|
|
41
|
-
this.clear();
|
|
42
|
-
data.forEach(row => {
|
|
43
|
-
const circle = new Marker(latLongFunc(row), {
|
|
44
|
-
icon: this.createIcon(weightFunc(row), this._palette(weightFunc(row), extent[0], extent[1]), format),
|
|
45
|
-
origRow: row
|
|
46
|
-
} as any).on("click", e => this.clickHandler(e, row));
|
|
47
|
-
circle.bindTooltip("Weight: " + weightFunc(row));
|
|
48
|
-
this.add(circle);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Events ---
|
|
53
|
-
clickHandler(e, row) {
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
ClusterCircles.prototype._class += " map_ClusterCircles";
|
|
57
|
-
ClusterCircles.prototype._palette = Palette.rainbow("default");
|
|
58
|
-
|
|
59
|
-
export interface ClusterCircles {
|
|
60
|
-
paletteID(): string;
|
|
61
|
-
paletteID(_: string): this;
|
|
62
|
-
paletteID_exists(): boolean;
|
|
63
|
-
useClonedPalette(): boolean;
|
|
64
|
-
useClonedPalette(_: boolean): this;
|
|
65
|
-
useClonedPalette_exists(): boolean;
|
|
66
|
-
|
|
67
|
-
latitudeColumn(): string;
|
|
68
|
-
latitudeColumn(_: string): this;
|
|
69
|
-
longitudeColumn(): string;
|
|
70
|
-
longitudeColumn(_: string): this;
|
|
71
|
-
weightColumn(): string;
|
|
72
|
-
weightColumn(_: string): this;
|
|
73
|
-
weightFormat(): string;
|
|
74
|
-
weightFormat(_: string): this;
|
|
75
|
-
|
|
76
|
-
opacity(): number;
|
|
77
|
-
opacity(_: number): this;
|
|
78
|
-
opacity_default(_: number): this;
|
|
79
|
-
opacity_exists(): boolean;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
ClusterCircles.prototype.publish("paletteID", "YlOrRd", "set", "Color palette for this widget", ClusterCircles.prototype._palette.switch());
|
|
83
|
-
ClusterCircles.prototype.publish("useClonedPalette", false, "boolean", "Enable or disable using a cloned palette");
|
|
84
|
-
ClusterCircles.prototype.publish("latitudeColumn", null, "set", "Latitude column", function () { return this.columns(); }, { optional: true });
|
|
85
|
-
ClusterCircles.prototype.publish("longitudeColumn", null, "set", "Longitude column", function () { return this.columns(); }, { optional: true });
|
|
86
|
-
ClusterCircles.prototype.publish("weightColumn", null, "set", "Weight column", function () { return this.columns(); }, { optional: true });
|
|
87
|
-
ClusterCircles.prototype.publish("weightFormat", ",", "string", "Number format for weight");
|
|
88
|
-
ClusterCircles.prototype.publish("opacity", 0.66, "number", "Opacity", null, { tags: ["Advanced"] });
|
|
1
|
+
import { extent as d3Extent, Palette } from "@hpcc-js/common";
|
|
2
|
+
import { DivIcon, Map, Marker, Point } from "./leaflet-shim.ts";
|
|
3
|
+
import { hsl as d3Hsl } from "d3-color";
|
|
4
|
+
import { format as d3Format } from "d3-format";
|
|
5
|
+
import { FeatureLayer } from "./FeatureLayer.ts";
|
|
6
|
+
|
|
7
|
+
import "../../src/leaflet/ClusterCircles.css";
|
|
8
|
+
|
|
9
|
+
export class ClusterCircles extends FeatureLayer {
|
|
10
|
+
|
|
11
|
+
_palette;
|
|
12
|
+
|
|
13
|
+
protected createIcon(childCount: number, backColor: string, format: (_: any) => any) {
|
|
14
|
+
const borderColor = d3Hsl(backColor);
|
|
15
|
+
borderColor.opacity = 0.5;
|
|
16
|
+
return new DivIcon({
|
|
17
|
+
className: "cluster-circle",
|
|
18
|
+
iconSize: new Point(40, 40),
|
|
19
|
+
html: `<div style='opacity:${this.opacity()};background-color:${borderColor.toString()}'><div style='background-color:${backColor}'><span style='color:${Palette.textColor(backColor)}'>${format(childCount)}</span></div></div>`
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
layerUpdate(map: Map) {
|
|
24
|
+
super.layerUpdate(map);
|
|
25
|
+
this._palette = this._palette.switch(this.paletteID());
|
|
26
|
+
if (this.useClonedPalette()) {
|
|
27
|
+
this._palette = this._palette.cloneNotExists(this.paletteID() + "_" + this.id());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const latFunc = this.cellFunc(this.latitudeColumn(), 0);
|
|
31
|
+
const longFunc = this.cellFunc(this.longitudeColumn(), 0);
|
|
32
|
+
const latLongFunc = (row): [number, number] => [+latFunc(row), +longFunc(row)];
|
|
33
|
+
const weightFunc = this.cellFunc(this.weightColumn(), 0);
|
|
34
|
+
|
|
35
|
+
const data: any[][] = this.data();
|
|
36
|
+
|
|
37
|
+
const extent = d3Extent(data, weightFunc);
|
|
38
|
+
|
|
39
|
+
const format = this.weightFormat() ? d3Format(this.weightFormat()) : _ => _;
|
|
40
|
+
|
|
41
|
+
this.clear();
|
|
42
|
+
data.forEach(row => {
|
|
43
|
+
const circle = new Marker(latLongFunc(row), {
|
|
44
|
+
icon: this.createIcon(weightFunc(row), this._palette(weightFunc(row), extent[0], extent[1]), format),
|
|
45
|
+
origRow: row
|
|
46
|
+
} as any).on("click", e => this.clickHandler(e, row));
|
|
47
|
+
circle.bindTooltip("Weight: " + weightFunc(row));
|
|
48
|
+
this.add(circle);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Events ---
|
|
53
|
+
clickHandler(e, row) {
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
ClusterCircles.prototype._class += " map_ClusterCircles";
|
|
57
|
+
ClusterCircles.prototype._palette = Palette.rainbow("default");
|
|
58
|
+
|
|
59
|
+
export interface ClusterCircles {
|
|
60
|
+
paletteID(): string;
|
|
61
|
+
paletteID(_: string): this;
|
|
62
|
+
paletteID_exists(): boolean;
|
|
63
|
+
useClonedPalette(): boolean;
|
|
64
|
+
useClonedPalette(_: boolean): this;
|
|
65
|
+
useClonedPalette_exists(): boolean;
|
|
66
|
+
|
|
67
|
+
latitudeColumn(): string;
|
|
68
|
+
latitudeColumn(_: string): this;
|
|
69
|
+
longitudeColumn(): string;
|
|
70
|
+
longitudeColumn(_: string): this;
|
|
71
|
+
weightColumn(): string;
|
|
72
|
+
weightColumn(_: string): this;
|
|
73
|
+
weightFormat(): string;
|
|
74
|
+
weightFormat(_: string): this;
|
|
75
|
+
|
|
76
|
+
opacity(): number;
|
|
77
|
+
opacity(_: number): this;
|
|
78
|
+
opacity_default(_: number): this;
|
|
79
|
+
opacity_exists(): boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
ClusterCircles.prototype.publish("paletteID", "YlOrRd", "set", "Color palette for this widget", ClusterCircles.prototype._palette.switch());
|
|
83
|
+
ClusterCircles.prototype.publish("useClonedPalette", false, "boolean", "Enable or disable using a cloned palette");
|
|
84
|
+
ClusterCircles.prototype.publish("latitudeColumn", null, "set", "Latitude column", function () { return this.columns(); }, { optional: true });
|
|
85
|
+
ClusterCircles.prototype.publish("longitudeColumn", null, "set", "Longitude column", function () { return this.columns(); }, { optional: true });
|
|
86
|
+
ClusterCircles.prototype.publish("weightColumn", null, "set", "Weight column", function () { return this.columns(); }, { optional: true });
|
|
87
|
+
ClusterCircles.prototype.publish("weightFormat", ",", "string", "Number format for weight");
|
|
88
|
+
ClusterCircles.prototype.publish("opacity", 0.66, "number", "Opacity", null, { tags: ["Advanced"] });
|
package/src/leaflet/Countries.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import { json as d3Json } from "d3-request";
|
|
2
|
-
import * as topojson from "topojson-client";
|
|
3
|
-
import { topoJsonFolder } from "../Choropleth.ts";
|
|
4
|
-
import { World } from "./World.ts";
|
|
5
|
-
|
|
6
|
-
let countries = null;
|
|
7
|
-
|
|
8
|
-
export class Countries extends World {
|
|
9
|
-
|
|
10
|
-
constructor() {
|
|
11
|
-
super();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
init(): Promise<void> {
|
|
15
|
-
if (!this._initPromise) {
|
|
16
|
-
this._initPromise = new Promise((resolve, reject) => {
|
|
17
|
-
if (countries) {
|
|
18
|
-
resolve(countries);
|
|
19
|
-
}
|
|
20
|
-
d3Json(`${topoJsonFolder()}/countries.json`, function (_countries) {
|
|
21
|
-
countries = _countries;
|
|
22
|
-
resolve(countries);
|
|
23
|
-
});
|
|
24
|
-
}).then((countries: any) => {
|
|
25
|
-
this._features = topojson.feature(countries.topology, countries.topology.objects.countries).features;
|
|
26
|
-
for (const key in this._features) {
|
|
27
|
-
if (this._features[key].id) {
|
|
28
|
-
const code = this._features[key].id;
|
|
29
|
-
const name = countries.countryNames[code]?.name;
|
|
30
|
-
this._features[key].properties.hpccID = name;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
return this._initPromise;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
tooltipHandler(l, featureID) {
|
|
39
|
-
const row = this._dataMap[featureID];
|
|
40
|
-
const value = row && row[1] || "";
|
|
41
|
-
return this.tooltipText(this.rowToObj(row), `<b>${featureID}</b>: ${value}`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
1
|
+
import { json as d3Json } from "d3-request";
|
|
2
|
+
import * as topojson from "topojson-client";
|
|
3
|
+
import { topoJsonFolder } from "../Choropleth.ts";
|
|
4
|
+
import { World } from "./World.ts";
|
|
5
|
+
|
|
6
|
+
let countries = null;
|
|
7
|
+
|
|
8
|
+
export class Countries extends World {
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
init(): Promise<void> {
|
|
15
|
+
if (!this._initPromise) {
|
|
16
|
+
this._initPromise = new Promise((resolve, reject) => {
|
|
17
|
+
if (countries) {
|
|
18
|
+
resolve(countries);
|
|
19
|
+
}
|
|
20
|
+
d3Json(`${topoJsonFolder()}/countries.json`, function (_countries) {
|
|
21
|
+
countries = _countries;
|
|
22
|
+
resolve(countries);
|
|
23
|
+
});
|
|
24
|
+
}).then((countries: any) => {
|
|
25
|
+
this._features = topojson.feature(countries.topology, countries.topology.objects.countries).features;
|
|
26
|
+
for (const key in this._features) {
|
|
27
|
+
if (this._features[key].id) {
|
|
28
|
+
const code = this._features[key].id;
|
|
29
|
+
const name = countries.countryNames[code]?.name;
|
|
30
|
+
this._features[key].properties.hpccID = name;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return this._initPromise;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
tooltipHandler(l, featureID) {
|
|
39
|
+
const row = this._dataMap[featureID];
|
|
40
|
+
const value = row && row[1] || "";
|
|
41
|
+
return this.tooltipText(this.rowToObj(row), `<b>${featureID}</b>: ${value}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/leaflet/DrawLayer.ts
CHANGED
|
@@ -1,167 +1,167 @@
|
|
|
1
|
-
import { Circle, Control, Draw, LatLng, LatLngBounds, LatLngExpression, Map, Polygon, Polyline, Rectangle } from "./leaflet-shim.ts";
|
|
2
|
-
import { hashSum } from "@hpcc-js/util";
|
|
3
|
-
import { FeatureLayer } from "./FeatureLayer.ts";
|
|
4
|
-
|
|
5
|
-
function del(arr: any[], item: object) {
|
|
6
|
-
const idx = arr.indexOf(item);
|
|
7
|
-
if (idx >= 0) {
|
|
8
|
-
arr.splice(idx, 1);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface DrawState {
|
|
13
|
-
polylines: LatLngExpression[][];
|
|
14
|
-
polygons: Array<LatLng[] | LatLng[][] | LatLng[][][]>;
|
|
15
|
-
rectangles: LatLngBounds[];
|
|
16
|
-
circles: Array<{ center: LatLng, radius: number }>;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export class DrawLayer extends FeatureLayer {
|
|
20
|
-
|
|
21
|
-
protected _polylines: Polyline[] = [];
|
|
22
|
-
protected _polygons: Polygon[] = [];
|
|
23
|
-
protected _rectangles: Rectangle[] = [];
|
|
24
|
-
protected _circles: Circle[] = [];
|
|
25
|
-
|
|
26
|
-
private _drawControl: Control.Draw;
|
|
27
|
-
|
|
28
|
-
hasBounds(): boolean {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
drawOptions(): Control.DrawOptions {
|
|
33
|
-
const retVal: Control.DrawOptions = {
|
|
34
|
-
marker: false,
|
|
35
|
-
circlemarker: false
|
|
36
|
-
};
|
|
37
|
-
if (!this.enableCircle()) {
|
|
38
|
-
retVal.circle = false;
|
|
39
|
-
}
|
|
40
|
-
if (!this.enablePolyline()) {
|
|
41
|
-
retVal.polyline = false;
|
|
42
|
-
}
|
|
43
|
-
if (!this.enableRectangle()) {
|
|
44
|
-
retVal.rectangle = false;
|
|
45
|
-
}
|
|
46
|
-
if (!this.enablePolygon()) {
|
|
47
|
-
retVal.polygon = false;
|
|
48
|
-
}
|
|
49
|
-
return retVal;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
save(): DrawState {
|
|
53
|
-
return {
|
|
54
|
-
polylines: this._polylines.map(p => p.getLatLngs() as LatLngExpression[]),
|
|
55
|
-
polygons: this._polygons.map(p => p.getLatLngs()),
|
|
56
|
-
rectangles: this._rectangles.map(r => r.getBounds()),
|
|
57
|
-
circles: this._circles.map(c => ({ center: c.getLatLng(), radius: c.getRadius() }))
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
restore(_: DrawState) {
|
|
62
|
-
this.clear();
|
|
63
|
-
this._polylines = (_.polylines || []).map(p => new Polyline(p));
|
|
64
|
-
this._polygons = (_.polygons || []).map(p => new Polygon(p));
|
|
65
|
-
this._rectangles = (_.rectangles || []).map(r => new Rectangle(r));
|
|
66
|
-
this._circles = (_.circles || []).map(c => new Circle(c.center, { radius: c.radius }));
|
|
67
|
-
this._polylines.forEach(_ => this.add(_));
|
|
68
|
-
this._polygons.forEach(_ => this.add(_));
|
|
69
|
-
this._rectangles.forEach(_ => this.add(_));
|
|
70
|
-
this._circles.forEach(_ => this.add(_));
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
private _drawOptionsHash;
|
|
74
|
-
layerEnter(map: Map) {
|
|
75
|
-
super.layerEnter(map);
|
|
76
|
-
|
|
77
|
-
map.on(Draw.Event.CREATED, (e: any) => {
|
|
78
|
-
const type = e.layerType;
|
|
79
|
-
const layer = e.layer;
|
|
80
|
-
switch (type) {
|
|
81
|
-
case "polyline":
|
|
82
|
-
this._polylines.push(layer);
|
|
83
|
-
break;
|
|
84
|
-
case "polygon":
|
|
85
|
-
this._polygons.push(layer);
|
|
86
|
-
break;
|
|
87
|
-
case "rectangle":
|
|
88
|
-
this._rectangles.push(layer);
|
|
89
|
-
break;
|
|
90
|
-
case "circle":
|
|
91
|
-
this._circles.push(layer);
|
|
92
|
-
break;
|
|
93
|
-
default:
|
|
94
|
-
alert(type);
|
|
95
|
-
}
|
|
96
|
-
this.add(layer);
|
|
97
|
-
this.changed("ADD", layer);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
map.on(Draw.Event.EDITED, (e: any) => {
|
|
101
|
-
const layers = e.layers;
|
|
102
|
-
layers.eachLayer(layer => {
|
|
103
|
-
this.changed("UPDATE", layer);
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
map.on(Draw.Event.DELETED, (e: any) => {
|
|
108
|
-
const layers = e.layers;
|
|
109
|
-
layers.eachLayer(layer => {
|
|
110
|
-
del(this._polylines, layer);
|
|
111
|
-
del(this._polygons, layer);
|
|
112
|
-
del(this._rectangles, layer);
|
|
113
|
-
del(this._circles, layer);
|
|
114
|
-
this.changed("DELETE", layer);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
layerUpdate(map: Map) {
|
|
120
|
-
super.layerUpdate(map);
|
|
121
|
-
this.style("opacity", this.opacity());
|
|
122
|
-
const drawOptions = this.drawOptions();
|
|
123
|
-
const drawOptionsHash = hashSum(drawOptions);
|
|
124
|
-
if (this._drawOptionsHash !== drawOptionsHash) {
|
|
125
|
-
this._drawOptionsHash = drawOptionsHash;
|
|
126
|
-
if (this._drawControl) {
|
|
127
|
-
map.removeControl(this._drawControl);
|
|
128
|
-
}
|
|
129
|
-
this._drawControl = new Control.Draw({
|
|
130
|
-
position: "topleft",
|
|
131
|
-
draw: drawOptions,
|
|
132
|
-
edit: {
|
|
133
|
-
featureGroup: this._layer
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
map.addControl(this._drawControl);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
layerExit(map: Map) {
|
|
141
|
-
super.layerExit(map);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Events ---
|
|
145
|
-
changed(type: "ADD" | "UPDATE" | "DELETE", items) {
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
DrawLayer.prototype._class += " map_DrawLayer";
|
|
149
|
-
|
|
150
|
-
export interface DrawLayer {
|
|
151
|
-
opacity(): number;
|
|
152
|
-
opacity(_: number): this;
|
|
153
|
-
enablePolyline(): boolean;
|
|
154
|
-
enablePolyline(_: boolean): this;
|
|
155
|
-
enablePolygon(): boolean;
|
|
156
|
-
enablePolygon(_: boolean): this;
|
|
157
|
-
enableRectangle(): boolean;
|
|
158
|
-
enableRectangle(_: boolean): this;
|
|
159
|
-
enableCircle(): boolean;
|
|
160
|
-
enableCircle(_: boolean): this;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
DrawLayer.prototype.publish("opacity", 1, "number", "Layer Opacity");
|
|
164
|
-
DrawLayer.prototype.publish("enablePolyline", true, "boolean", "Enable Polyline Creation");
|
|
165
|
-
DrawLayer.prototype.publish("enablePolygon", true, "boolean", "Enable Polygon Creation");
|
|
166
|
-
DrawLayer.prototype.publish("enableRectangle", true, "boolean", "Enable Rectangle Creation");
|
|
167
|
-
DrawLayer.prototype.publish("enableCircle", true, "boolean", "Enable Circle Creation");
|
|
1
|
+
import { Circle, Control, Draw, LatLng, LatLngBounds, LatLngExpression, Map, Polygon, Polyline, Rectangle } from "./leaflet-shim.ts";
|
|
2
|
+
import { hashSum } from "@hpcc-js/util";
|
|
3
|
+
import { FeatureLayer } from "./FeatureLayer.ts";
|
|
4
|
+
|
|
5
|
+
function del(arr: any[], item: object) {
|
|
6
|
+
const idx = arr.indexOf(item);
|
|
7
|
+
if (idx >= 0) {
|
|
8
|
+
arr.splice(idx, 1);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface DrawState {
|
|
13
|
+
polylines: LatLngExpression[][];
|
|
14
|
+
polygons: Array<LatLng[] | LatLng[][] | LatLng[][][]>;
|
|
15
|
+
rectangles: LatLngBounds[];
|
|
16
|
+
circles: Array<{ center: LatLng, radius: number }>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class DrawLayer extends FeatureLayer {
|
|
20
|
+
|
|
21
|
+
protected _polylines: Polyline[] = [];
|
|
22
|
+
protected _polygons: Polygon[] = [];
|
|
23
|
+
protected _rectangles: Rectangle[] = [];
|
|
24
|
+
protected _circles: Circle[] = [];
|
|
25
|
+
|
|
26
|
+
private _drawControl: Control.Draw;
|
|
27
|
+
|
|
28
|
+
hasBounds(): boolean {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
drawOptions(): Control.DrawOptions {
|
|
33
|
+
const retVal: Control.DrawOptions = {
|
|
34
|
+
marker: false,
|
|
35
|
+
circlemarker: false
|
|
36
|
+
};
|
|
37
|
+
if (!this.enableCircle()) {
|
|
38
|
+
retVal.circle = false;
|
|
39
|
+
}
|
|
40
|
+
if (!this.enablePolyline()) {
|
|
41
|
+
retVal.polyline = false;
|
|
42
|
+
}
|
|
43
|
+
if (!this.enableRectangle()) {
|
|
44
|
+
retVal.rectangle = false;
|
|
45
|
+
}
|
|
46
|
+
if (!this.enablePolygon()) {
|
|
47
|
+
retVal.polygon = false;
|
|
48
|
+
}
|
|
49
|
+
return retVal;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
save(): DrawState {
|
|
53
|
+
return {
|
|
54
|
+
polylines: this._polylines.map(p => p.getLatLngs() as LatLngExpression[]),
|
|
55
|
+
polygons: this._polygons.map(p => p.getLatLngs()),
|
|
56
|
+
rectangles: this._rectangles.map(r => r.getBounds()),
|
|
57
|
+
circles: this._circles.map(c => ({ center: c.getLatLng(), radius: c.getRadius() }))
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
restore(_: DrawState) {
|
|
62
|
+
this.clear();
|
|
63
|
+
this._polylines = (_.polylines || []).map(p => new Polyline(p));
|
|
64
|
+
this._polygons = (_.polygons || []).map(p => new Polygon(p));
|
|
65
|
+
this._rectangles = (_.rectangles || []).map(r => new Rectangle(r));
|
|
66
|
+
this._circles = (_.circles || []).map(c => new Circle(c.center, { radius: c.radius }));
|
|
67
|
+
this._polylines.forEach(_ => this.add(_));
|
|
68
|
+
this._polygons.forEach(_ => this.add(_));
|
|
69
|
+
this._rectangles.forEach(_ => this.add(_));
|
|
70
|
+
this._circles.forEach(_ => this.add(_));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private _drawOptionsHash;
|
|
74
|
+
layerEnter(map: Map) {
|
|
75
|
+
super.layerEnter(map);
|
|
76
|
+
|
|
77
|
+
map.on(Draw.Event.CREATED, (e: any) => {
|
|
78
|
+
const type = e.layerType;
|
|
79
|
+
const layer = e.layer;
|
|
80
|
+
switch (type) {
|
|
81
|
+
case "polyline":
|
|
82
|
+
this._polylines.push(layer);
|
|
83
|
+
break;
|
|
84
|
+
case "polygon":
|
|
85
|
+
this._polygons.push(layer);
|
|
86
|
+
break;
|
|
87
|
+
case "rectangle":
|
|
88
|
+
this._rectangles.push(layer);
|
|
89
|
+
break;
|
|
90
|
+
case "circle":
|
|
91
|
+
this._circles.push(layer);
|
|
92
|
+
break;
|
|
93
|
+
default:
|
|
94
|
+
alert(type);
|
|
95
|
+
}
|
|
96
|
+
this.add(layer);
|
|
97
|
+
this.changed("ADD", layer);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
map.on(Draw.Event.EDITED, (e: any) => {
|
|
101
|
+
const layers = e.layers;
|
|
102
|
+
layers.eachLayer(layer => {
|
|
103
|
+
this.changed("UPDATE", layer);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
map.on(Draw.Event.DELETED, (e: any) => {
|
|
108
|
+
const layers = e.layers;
|
|
109
|
+
layers.eachLayer(layer => {
|
|
110
|
+
del(this._polylines, layer);
|
|
111
|
+
del(this._polygons, layer);
|
|
112
|
+
del(this._rectangles, layer);
|
|
113
|
+
del(this._circles, layer);
|
|
114
|
+
this.changed("DELETE", layer);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
layerUpdate(map: Map) {
|
|
120
|
+
super.layerUpdate(map);
|
|
121
|
+
this.style("opacity", this.opacity());
|
|
122
|
+
const drawOptions = this.drawOptions();
|
|
123
|
+
const drawOptionsHash = hashSum(drawOptions);
|
|
124
|
+
if (this._drawOptionsHash !== drawOptionsHash) {
|
|
125
|
+
this._drawOptionsHash = drawOptionsHash;
|
|
126
|
+
if (this._drawControl) {
|
|
127
|
+
map.removeControl(this._drawControl);
|
|
128
|
+
}
|
|
129
|
+
this._drawControl = new Control.Draw({
|
|
130
|
+
position: "topleft",
|
|
131
|
+
draw: drawOptions,
|
|
132
|
+
edit: {
|
|
133
|
+
featureGroup: this._layer
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
map.addControl(this._drawControl);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
layerExit(map: Map) {
|
|
141
|
+
super.layerExit(map);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Events ---
|
|
145
|
+
changed(type: "ADD" | "UPDATE" | "DELETE", items) {
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
DrawLayer.prototype._class += " map_DrawLayer";
|
|
149
|
+
|
|
150
|
+
export interface DrawLayer {
|
|
151
|
+
opacity(): number;
|
|
152
|
+
opacity(_: number): this;
|
|
153
|
+
enablePolyline(): boolean;
|
|
154
|
+
enablePolyline(_: boolean): this;
|
|
155
|
+
enablePolygon(): boolean;
|
|
156
|
+
enablePolygon(_: boolean): this;
|
|
157
|
+
enableRectangle(): boolean;
|
|
158
|
+
enableRectangle(_: boolean): this;
|
|
159
|
+
enableCircle(): boolean;
|
|
160
|
+
enableCircle(_: boolean): this;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
DrawLayer.prototype.publish("opacity", 1, "number", "Layer Opacity");
|
|
164
|
+
DrawLayer.prototype.publish("enablePolyline", true, "boolean", "Enable Polyline Creation");
|
|
165
|
+
DrawLayer.prototype.publish("enablePolygon", true, "boolean", "Enable Polygon Creation");
|
|
166
|
+
DrawLayer.prototype.publish("enableRectangle", true, "boolean", "Enable Rectangle Creation");
|
|
167
|
+
DrawLayer.prototype.publish("enableCircle", true, "boolean", "Enable Circle Creation");
|