@hpcc-js/map 3.5.2 → 3.5.4
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 +9 -9
- package/src/CanvasPinLayer.ts +99 -99
- package/src/CanvasPins.ts +397 -397
- package/src/Choropleth.css +26 -26
- 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 +20 -20
- 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 +14 -14
- package/src/GeoHash.ts +139 -139
- package/src/Graph.css +9 -9
- package/src/Graph.ts +98 -98
- package/src/Graticule.css +12 -12
- package/src/Graticule.ts +97 -97
- package/src/Heat.ts +87 -87
- package/src/IChoropleth.ts +8 -8
- package/src/Layer.ts +99 -99
- package/src/Layered.css +18 -18
- package/src/Layered.ts +206 -206
- package/src/Lines.css +8 -8
- package/src/Lines.ts +78 -78
- package/src/OpenStreet.css +15 -15
- package/src/OpenStreet.ts +126 -126
- package/src/Pins.css +17 -17
- 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 +2 -2
- 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
- package/types/Layered.d.ts +1 -1
package/src/leaflet/Pins.ts
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import { BeautifyIcon, Map } from "./leaflet-shim.ts";
|
|
2
|
-
import { Markers } from "./Markers.ts";
|
|
3
|
-
|
|
4
|
-
export class Pins extends Markers {
|
|
5
|
-
|
|
6
|
-
constructor(cluster = false) {
|
|
7
|
-
super(cluster);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
layerUpdate(map: Map) {
|
|
11
|
-
const columns = this.columns();
|
|
12
|
-
const faCharIdx = columns.indexOf(this.faCharColumn());
|
|
13
|
-
const faCharColorIdx = columns.indexOf(this.faCharColorColumn());
|
|
14
|
-
const strokeColorIdx = columns.indexOf(this.strokeColorColumn());
|
|
15
|
-
const fillColorIdx = columns.indexOf(this.fillColorColumn());
|
|
16
|
-
super.layerUpdate(map, (row) => {
|
|
17
|
-
return {
|
|
18
|
-
icon: BeautifyIcon({
|
|
19
|
-
iconShape: "marker",
|
|
20
|
-
icon: this.propValue(faCharIdx, row, this.faChar()),
|
|
21
|
-
textColor: this.propValue(faCharColorIdx, row, this.faCharColor()),
|
|
22
|
-
borderColor: this.propValue(strokeColorIdx, row, this.strokeColor()),
|
|
23
|
-
backgroundColor: this.propValue(fillColorIdx, row, this.fillColor()),
|
|
24
|
-
props: {
|
|
25
|
-
owner: this,
|
|
26
|
-
row
|
|
27
|
-
}
|
|
28
|
-
}),
|
|
29
|
-
draggable: false
|
|
30
|
-
};
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
Pins.prototype._class += " map_Pins";
|
|
35
|
-
|
|
36
|
-
export interface Pins {
|
|
37
|
-
faChar(): string;
|
|
38
|
-
faChar(_: string);
|
|
39
|
-
faCharColumn(): string;
|
|
40
|
-
faCharColumn(_: string);
|
|
41
|
-
faCharColumn_exists(): boolean;
|
|
42
|
-
faCharColor(): string;
|
|
43
|
-
faCharColor(_: string);
|
|
44
|
-
faCharColorColumn(): string;
|
|
45
|
-
faCharColorColumn(_: string);
|
|
46
|
-
faCharColorColumn_exists(): boolean;
|
|
47
|
-
strokeColor(): string;
|
|
48
|
-
strokeColor(_: string);
|
|
49
|
-
strokeColorColumn(): string;
|
|
50
|
-
strokeColorColumn(_: string);
|
|
51
|
-
strokColorColumn_exists(): boolean;
|
|
52
|
-
fillColor(): string;
|
|
53
|
-
fillColor(_: string);
|
|
54
|
-
fillColorColumn(): string;
|
|
55
|
-
fillColorColumn(_: string);
|
|
56
|
-
fillColorColumn_exists(): boolean;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
Pins.prototype.publish("faChar", "fa-circle", "string", "Default font awesome character");
|
|
60
|
-
Pins.prototype.publish("faCharColumn", null, "set", "Font awesome column", function () { return this.columns(); }, { optional: true });
|
|
61
|
-
Pins.prototype.publish("faCharColor", "#ffffff", "html-color", "Default font awesome Color");
|
|
62
|
-
Pins.prototype.publish("faCharColorColumn", null, "set", "Font awesome color column", function () { return this.columns(); }, { optional: true });
|
|
63
|
-
Pins.prototype.publish("strokeColor", "transparent", "html-color", "Default stroke Color", null, { optional: true });
|
|
64
|
-
Pins.prototype.publish("strokeColorColumn", null, "set", "Stroke color column", function () { return this.columns(); }, { optional: true });
|
|
65
|
-
Pins.prototype.publish("fillColor", "#376cea", "html-color", "Default fill Color", null, { optional: true });
|
|
66
|
-
Pins.prototype.publish("fillColorColumn", null, "set", "Fill color column", function () { return this.columns(); }, { optional: true });
|
|
67
|
-
|
|
68
|
-
export class ClusterPins extends Pins {
|
|
69
|
-
constructor() {
|
|
70
|
-
super(true);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
ClusterPins.prototype._class += " map_ClusterPins";
|
|
1
|
+
import { BeautifyIcon, Map } from "./leaflet-shim.ts";
|
|
2
|
+
import { Markers } from "./Markers.ts";
|
|
3
|
+
|
|
4
|
+
export class Pins extends Markers {
|
|
5
|
+
|
|
6
|
+
constructor(cluster = false) {
|
|
7
|
+
super(cluster);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
layerUpdate(map: Map) {
|
|
11
|
+
const columns = this.columns();
|
|
12
|
+
const faCharIdx = columns.indexOf(this.faCharColumn());
|
|
13
|
+
const faCharColorIdx = columns.indexOf(this.faCharColorColumn());
|
|
14
|
+
const strokeColorIdx = columns.indexOf(this.strokeColorColumn());
|
|
15
|
+
const fillColorIdx = columns.indexOf(this.fillColorColumn());
|
|
16
|
+
super.layerUpdate(map, (row) => {
|
|
17
|
+
return {
|
|
18
|
+
icon: BeautifyIcon({
|
|
19
|
+
iconShape: "marker",
|
|
20
|
+
icon: this.propValue(faCharIdx, row, this.faChar()),
|
|
21
|
+
textColor: this.propValue(faCharColorIdx, row, this.faCharColor()),
|
|
22
|
+
borderColor: this.propValue(strokeColorIdx, row, this.strokeColor()),
|
|
23
|
+
backgroundColor: this.propValue(fillColorIdx, row, this.fillColor()),
|
|
24
|
+
props: {
|
|
25
|
+
owner: this,
|
|
26
|
+
row
|
|
27
|
+
}
|
|
28
|
+
}),
|
|
29
|
+
draggable: false
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
Pins.prototype._class += " map_Pins";
|
|
35
|
+
|
|
36
|
+
export interface Pins {
|
|
37
|
+
faChar(): string;
|
|
38
|
+
faChar(_: string);
|
|
39
|
+
faCharColumn(): string;
|
|
40
|
+
faCharColumn(_: string);
|
|
41
|
+
faCharColumn_exists(): boolean;
|
|
42
|
+
faCharColor(): string;
|
|
43
|
+
faCharColor(_: string);
|
|
44
|
+
faCharColorColumn(): string;
|
|
45
|
+
faCharColorColumn(_: string);
|
|
46
|
+
faCharColorColumn_exists(): boolean;
|
|
47
|
+
strokeColor(): string;
|
|
48
|
+
strokeColor(_: string);
|
|
49
|
+
strokeColorColumn(): string;
|
|
50
|
+
strokeColorColumn(_: string);
|
|
51
|
+
strokColorColumn_exists(): boolean;
|
|
52
|
+
fillColor(): string;
|
|
53
|
+
fillColor(_: string);
|
|
54
|
+
fillColorColumn(): string;
|
|
55
|
+
fillColorColumn(_: string);
|
|
56
|
+
fillColorColumn_exists(): boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
Pins.prototype.publish("faChar", "fa-circle", "string", "Default font awesome character");
|
|
60
|
+
Pins.prototype.publish("faCharColumn", null, "set", "Font awesome column", function () { return this.columns(); }, { optional: true });
|
|
61
|
+
Pins.prototype.publish("faCharColor", "#ffffff", "html-color", "Default font awesome Color");
|
|
62
|
+
Pins.prototype.publish("faCharColorColumn", null, "set", "Font awesome color column", function () { return this.columns(); }, { optional: true });
|
|
63
|
+
Pins.prototype.publish("strokeColor", "transparent", "html-color", "Default stroke Color", null, { optional: true });
|
|
64
|
+
Pins.prototype.publish("strokeColorColumn", null, "set", "Stroke color column", function () { return this.columns(); }, { optional: true });
|
|
65
|
+
Pins.prototype.publish("fillColor", "#376cea", "html-color", "Default fill Color", null, { optional: true });
|
|
66
|
+
Pins.prototype.publish("fillColorColumn", null, "set", "Fill color column", function () { return this.columns(); }, { optional: true });
|
|
67
|
+
|
|
68
|
+
export class ClusterPins extends Pins {
|
|
69
|
+
constructor() {
|
|
70
|
+
super(true);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
ClusterPins.prototype._class += " map_ClusterPins";
|
package/src/leaflet/Polygons.ts
CHANGED
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
import { extent as d3Extent, Palette } from "@hpcc-js/common";
|
|
2
|
-
import { LeafletEvent, Map, Polygon } from "./leaflet-shim.ts";
|
|
3
|
-
import { FeatureLayer } from "./FeatureLayer.ts";
|
|
4
|
-
|
|
5
|
-
function lngLat2LatLng(d: [number, number]): [number, number] {
|
|
6
|
-
return [d[1], d[0]];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
type Lat = number;
|
|
10
|
-
type Lon = number;
|
|
11
|
-
type Point = [Lon, Lat];
|
|
12
|
-
|
|
13
|
-
type Spread = [number, number];
|
|
14
|
-
const calcSpread = (prev: Spread, p: Point): Spread => {
|
|
15
|
-
if (p[0] < -90) prev[0]++;
|
|
16
|
-
else if (p[0] > 90) prev[1]++;
|
|
17
|
-
return prev;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const shiftLeft = (lng: number): number => lng > 90 ? lng - 360 : lng;
|
|
21
|
-
const shiftRight = (lng: number): number => lng < -90 ? lng + 360 : lng;
|
|
22
|
-
const shiftPoint = (left: boolean): (p: Point) => Point => {
|
|
23
|
-
const shiftFunc = left ? shiftLeft : shiftRight;
|
|
24
|
-
return (p: Point) => [shiftFunc(p[0]), p[1]];
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export class Polygons extends FeatureLayer {
|
|
28
|
-
|
|
29
|
-
_palette;
|
|
30
|
-
|
|
31
|
-
protected fixDateLine(points: Point[]): Point[] {
|
|
32
|
-
const [lhsCount, rhsCount] = points.reduce(calcSpread, [0, 0]);
|
|
33
|
-
if (lhsCount && rhsCount) {
|
|
34
|
-
return points.map(shiftPoint(lhsCount > rhsCount));
|
|
35
|
-
}
|
|
36
|
-
return points;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
hasBounds(): boolean {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
updateHexagons() {
|
|
44
|
-
this._palette = this._palette.switch(this.paletteID());
|
|
45
|
-
if (this.useClonedPalette()) {
|
|
46
|
-
this._palette = this._palette.cloneNotExists(this.paletteID() + "_" + this.id());
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const polyFunc = this.cellFunc(this.polygonColumn(), []);
|
|
50
|
-
const weightFunc = this.cellFunc(this.weightColumn(), 0);
|
|
51
|
-
|
|
52
|
-
const data = this.data();
|
|
53
|
-
|
|
54
|
-
const extent = d3Extent(data, weightFunc);
|
|
55
|
-
|
|
56
|
-
this.clear();
|
|
57
|
-
data.forEach(row => {
|
|
58
|
-
this.add(new Polygon(this.fixDateLine(polyFunc(row)).map(lngLat2LatLng), {
|
|
59
|
-
color: this._palette(extent[1], extent[0], extent[1]),
|
|
60
|
-
fillColor: this._palette(weightFunc(row), extent[0], extent[1]),
|
|
61
|
-
fillOpacity: this.opacity(),
|
|
62
|
-
weight: 1,
|
|
63
|
-
origRow: row
|
|
64
|
-
} as any).on("click", e => this.clickHandler(e, row)));
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
layerUpdate(map: Map) {
|
|
69
|
-
super.layerUpdate(map);
|
|
70
|
-
this.updateHexagons();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Events ---
|
|
74
|
-
zoomEnd(e: LeafletEvent) {
|
|
75
|
-
super.zoomEnd(e);
|
|
76
|
-
// this.updateHexagons();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
moveEnd(e: LeafletEvent) {
|
|
80
|
-
super.moveEnd(e);
|
|
81
|
-
this.updateHexagons();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
clickHandler(e, row) {
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
Polygons.prototype._class += " map_Polygons";
|
|
88
|
-
Polygons.prototype._palette = Palette.rainbow("default");
|
|
89
|
-
|
|
90
|
-
export interface Polygons {
|
|
91
|
-
paletteID(): string;
|
|
92
|
-
paletteID(_: string): this;
|
|
93
|
-
paletteID_exists(): boolean;
|
|
94
|
-
useClonedPalette(): boolean;
|
|
95
|
-
useClonedPalette(_: boolean): this;
|
|
96
|
-
useClonedPalette_exists(): boolean;
|
|
97
|
-
|
|
98
|
-
polygonColumn(): string;
|
|
99
|
-
polygonColumn(_: string): this;
|
|
100
|
-
weightColumn(): string;
|
|
101
|
-
weightColumn(_: string): this;
|
|
102
|
-
|
|
103
|
-
opacity(): number;
|
|
104
|
-
opacity(_: number): this;
|
|
105
|
-
opacity_default(_: number): this;
|
|
106
|
-
opacity_exists(): boolean;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
Polygons.prototype.publish("paletteID", "YlOrRd", "set", "Color palette for this widget", Polygons.prototype._palette.switch(), { tags: ["Basic", "Shared"] });
|
|
110
|
-
Polygons.prototype.publish("useClonedPalette", false, "boolean", "Enable or disable using a cloned palette", null, { tags: ["Intermediate", "Shared"] });
|
|
111
|
-
Polygons.prototype.publish("polygonColumn", null, "set", "Polygon column", function () { return this.columns(); }, { optional: true });
|
|
112
|
-
Polygons.prototype.publish("weightColumn", null, "set", "Weight column", function () { return this.columns(); }, { optional: true });
|
|
113
|
-
Polygons.prototype.publish("opacity", 0.5, "number", "Opacity", null, { tags: ["Advanced"] });
|
|
1
|
+
import { extent as d3Extent, Palette } from "@hpcc-js/common";
|
|
2
|
+
import { LeafletEvent, Map, Polygon } from "./leaflet-shim.ts";
|
|
3
|
+
import { FeatureLayer } from "./FeatureLayer.ts";
|
|
4
|
+
|
|
5
|
+
function lngLat2LatLng(d: [number, number]): [number, number] {
|
|
6
|
+
return [d[1], d[0]];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type Lat = number;
|
|
10
|
+
type Lon = number;
|
|
11
|
+
type Point = [Lon, Lat];
|
|
12
|
+
|
|
13
|
+
type Spread = [number, number];
|
|
14
|
+
const calcSpread = (prev: Spread, p: Point): Spread => {
|
|
15
|
+
if (p[0] < -90) prev[0]++;
|
|
16
|
+
else if (p[0] > 90) prev[1]++;
|
|
17
|
+
return prev;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const shiftLeft = (lng: number): number => lng > 90 ? lng - 360 : lng;
|
|
21
|
+
const shiftRight = (lng: number): number => lng < -90 ? lng + 360 : lng;
|
|
22
|
+
const shiftPoint = (left: boolean): (p: Point) => Point => {
|
|
23
|
+
const shiftFunc = left ? shiftLeft : shiftRight;
|
|
24
|
+
return (p: Point) => [shiftFunc(p[0]), p[1]];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export class Polygons extends FeatureLayer {
|
|
28
|
+
|
|
29
|
+
_palette;
|
|
30
|
+
|
|
31
|
+
protected fixDateLine(points: Point[]): Point[] {
|
|
32
|
+
const [lhsCount, rhsCount] = points.reduce(calcSpread, [0, 0]);
|
|
33
|
+
if (lhsCount && rhsCount) {
|
|
34
|
+
return points.map(shiftPoint(lhsCount > rhsCount));
|
|
35
|
+
}
|
|
36
|
+
return points;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
hasBounds(): boolean {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
updateHexagons() {
|
|
44
|
+
this._palette = this._palette.switch(this.paletteID());
|
|
45
|
+
if (this.useClonedPalette()) {
|
|
46
|
+
this._palette = this._palette.cloneNotExists(this.paletteID() + "_" + this.id());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const polyFunc = this.cellFunc(this.polygonColumn(), []);
|
|
50
|
+
const weightFunc = this.cellFunc(this.weightColumn(), 0);
|
|
51
|
+
|
|
52
|
+
const data = this.data();
|
|
53
|
+
|
|
54
|
+
const extent = d3Extent(data, weightFunc);
|
|
55
|
+
|
|
56
|
+
this.clear();
|
|
57
|
+
data.forEach(row => {
|
|
58
|
+
this.add(new Polygon(this.fixDateLine(polyFunc(row)).map(lngLat2LatLng), {
|
|
59
|
+
color: this._palette(extent[1], extent[0], extent[1]),
|
|
60
|
+
fillColor: this._palette(weightFunc(row), extent[0], extent[1]),
|
|
61
|
+
fillOpacity: this.opacity(),
|
|
62
|
+
weight: 1,
|
|
63
|
+
origRow: row
|
|
64
|
+
} as any).on("click", e => this.clickHandler(e, row)));
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
layerUpdate(map: Map) {
|
|
69
|
+
super.layerUpdate(map);
|
|
70
|
+
this.updateHexagons();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Events ---
|
|
74
|
+
zoomEnd(e: LeafletEvent) {
|
|
75
|
+
super.zoomEnd(e);
|
|
76
|
+
// this.updateHexagons();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
moveEnd(e: LeafletEvent) {
|
|
80
|
+
super.moveEnd(e);
|
|
81
|
+
this.updateHexagons();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
clickHandler(e, row) {
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
Polygons.prototype._class += " map_Polygons";
|
|
88
|
+
Polygons.prototype._palette = Palette.rainbow("default");
|
|
89
|
+
|
|
90
|
+
export interface Polygons {
|
|
91
|
+
paletteID(): string;
|
|
92
|
+
paletteID(_: string): this;
|
|
93
|
+
paletteID_exists(): boolean;
|
|
94
|
+
useClonedPalette(): boolean;
|
|
95
|
+
useClonedPalette(_: boolean): this;
|
|
96
|
+
useClonedPalette_exists(): boolean;
|
|
97
|
+
|
|
98
|
+
polygonColumn(): string;
|
|
99
|
+
polygonColumn(_: string): this;
|
|
100
|
+
weightColumn(): string;
|
|
101
|
+
weightColumn(_: string): this;
|
|
102
|
+
|
|
103
|
+
opacity(): number;
|
|
104
|
+
opacity(_: number): this;
|
|
105
|
+
opacity_default(_: number): this;
|
|
106
|
+
opacity_exists(): boolean;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
Polygons.prototype.publish("paletteID", "YlOrRd", "set", "Color palette for this widget", Polygons.prototype._palette.switch(), { tags: ["Basic", "Shared"] });
|
|
110
|
+
Polygons.prototype.publish("useClonedPalette", false, "boolean", "Enable or disable using a cloned palette", null, { tags: ["Intermediate", "Shared"] });
|
|
111
|
+
Polygons.prototype.publish("polygonColumn", null, "set", "Polygon column", function () { return this.columns(); }, { optional: true });
|
|
112
|
+
Polygons.prototype.publish("weightColumn", null, "set", "Weight column", function () { return this.columns(); }, { optional: true });
|
|
113
|
+
Polygons.prototype.publish("opacity", 0.5, "number", "Opacity", null, { tags: ["Advanced"] });
|
package/src/leaflet/Region.ts
CHANGED
|
@@ -1,138 +1,138 @@
|
|
|
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
|
-
const topo_indexes = {
|
|
7
|
-
"GB": ["administrative_area_level_3", "administrative_area_level_2", "administrative_area_level_1"],
|
|
8
|
-
"IE": ["administrative_area_level_2", "administrative_area_level_1"],
|
|
9
|
-
"ND": ["administrative_area_level_2", "administrative_area_level_1"]
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
type NameCodes = { [name: string]: { code: any, codes: any[] } };
|
|
13
|
-
type CodeNames = { [code: string]: { name: string, score: number, names: string[] } };
|
|
14
|
-
type CachedItem = { topology: any, nameIdx: NameCodes, codeIdx: CodeNames };
|
|
15
|
-
const _cachedRegion: { [id: string]: CachedItem } = {};
|
|
16
|
-
function cachedRegion(id: string): CachedItem {
|
|
17
|
-
if (!_cachedRegion[id]) {
|
|
18
|
-
_cachedRegion[id] = {
|
|
19
|
-
topology: undefined,
|
|
20
|
-
nameIdx: {},
|
|
21
|
-
codeIdx: {}
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
return _cachedRegion[id];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class Region extends World {
|
|
28
|
-
|
|
29
|
-
constructor() {
|
|
30
|
-
super();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
protected fetchTopo(regionID: string) {
|
|
34
|
-
if (cachedRegion(regionID).topology) {
|
|
35
|
-
return Promise.resolve(cachedRegion(regionID).topology);
|
|
36
|
-
}
|
|
37
|
-
return new Promise((resolve, reject) => {
|
|
38
|
-
d3Json(`${topoJsonFolder()}/${regionID}.json`, function (region) {
|
|
39
|
-
cachedRegion(regionID).topology = region;
|
|
40
|
-
resolve(region);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
protected fetchTopoIdx(regionID: string) {
|
|
46
|
-
for (const _key in cachedRegion(regionID).nameIdx) {
|
|
47
|
-
return Promise.resolve(cachedRegion(regionID).nameIdx);
|
|
48
|
-
}
|
|
49
|
-
return new Promise((resolve, reject) => {
|
|
50
|
-
d3Json(`${topoJsonFolder()}/${regionID}_idx.json`, function (index) {
|
|
51
|
-
const { nameIdx, codeIdx } = cachedRegion(regionID);
|
|
52
|
-
topo_indexes[regionID]?.forEach(level => {
|
|
53
|
-
for (const name in index[level]) {
|
|
54
|
-
const codes = index[level][name];
|
|
55
|
-
if (Array.isArray(codes)) {
|
|
56
|
-
if (!nameIdx[name]) {
|
|
57
|
-
nameIdx[name] = { code: undefined, codes: [] };
|
|
58
|
-
}
|
|
59
|
-
nameIdx[name].codes = nameIdx[name].codes.concat(codes);
|
|
60
|
-
if (codes.length === 1) {
|
|
61
|
-
nameIdx[name].code = nameIdx[name].codes[0];
|
|
62
|
-
}
|
|
63
|
-
codes.forEach(code => {
|
|
64
|
-
if (!codeIdx[code]) {
|
|
65
|
-
codeIdx[code] = { name: undefined, score: 9999, names: [] };
|
|
66
|
-
}
|
|
67
|
-
if (codes.length <= codeIdx[code].score) {
|
|
68
|
-
codeIdx[code].name = name;
|
|
69
|
-
codeIdx[code].score = codes.length;
|
|
70
|
-
}
|
|
71
|
-
codeIdx[code].names.push(name);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
resolve(nameIdx);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
updateDataMap(_?) {
|
|
82
|
-
const expandedRetVal = [];
|
|
83
|
-
const nameIdx = cachedRegion(this.region()).nameIdx;
|
|
84
|
-
_.forEach(row => {
|
|
85
|
-
const codes = nameIdx[row[0]]?.codes;
|
|
86
|
-
if (codes) {
|
|
87
|
-
codes?.forEach(code => {
|
|
88
|
-
expandedRetVal.push([code, row[1], row]);
|
|
89
|
-
});
|
|
90
|
-
} else {
|
|
91
|
-
expandedRetVal.push([row[0], row[1], row]);
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
return super.updateDataMap(expandedRetVal);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
_prevRegion: string;
|
|
98
|
-
init(): Promise<void> {
|
|
99
|
-
const regionID = this.region();
|
|
100
|
-
if (!this._initPromise || this._prevRegion !== regionID) {
|
|
101
|
-
this._prevRegion = regionID;
|
|
102
|
-
this._initPromise = Promise.all([
|
|
103
|
-
this.fetchTopo(regionID),
|
|
104
|
-
this.fetchTopoIdx(regionID)
|
|
105
|
-
]).then(([region, index]: [any, any]) => {
|
|
106
|
-
this._features = topojson.feature(region, region.objects.PolbndA).features;
|
|
107
|
-
for (const key in this._features) {
|
|
108
|
-
const code = this._features[key].id || key;
|
|
109
|
-
this._features[key].properties.hpccID = code;
|
|
110
|
-
}
|
|
111
|
-
this.updateDataMap(this.data());
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
return this._initPromise;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
tooltipHandler(l, featureID) {
|
|
118
|
-
const row = this._dataMap[featureID];
|
|
119
|
-
const codeIdx = cachedRegion(this.region()).codeIdx;
|
|
120
|
-
const value = row && row[1] || "";
|
|
121
|
-
const featureName = codeIdx[featureID]?.names.map(name => {
|
|
122
|
-
if (codeIdx[featureID]?.name === name) {
|
|
123
|
-
return `<u>${name}</u>`;
|
|
124
|
-
}
|
|
125
|
-
return name;
|
|
126
|
-
}).join(", ");
|
|
127
|
-
return this.tooltipText(this.rowToObj(row), `<b>${row && row[2][0] || featureName || featureID}</b>: ${value}`);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
Region.prototype._class += " map_Region";
|
|
131
|
-
|
|
132
|
-
export interface Region {
|
|
133
|
-
region(): string;
|
|
134
|
-
region(_: string): this;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
Region.prototype.publish("region", "GB", "set", "Region Data", ["AT", "BE", "BG", "BR", "CHLI", "CY", "CZ", "DE", "DK", "EE", "ES", "FI", "FR", "GB", "GE", "GR", "HR", "HU", "IE", "IS", "IT", "KS", "LT", "LU", "LV", "MD", "MK", "MT", "ND", "NL", "NO", "PL", "PT", "RO", "RS", "SE", "SI", "SK", "UA"]);
|
|
138
|
-
|
|
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
|
+
const topo_indexes = {
|
|
7
|
+
"GB": ["administrative_area_level_3", "administrative_area_level_2", "administrative_area_level_1"],
|
|
8
|
+
"IE": ["administrative_area_level_2", "administrative_area_level_1"],
|
|
9
|
+
"ND": ["administrative_area_level_2", "administrative_area_level_1"]
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type NameCodes = { [name: string]: { code: any, codes: any[] } };
|
|
13
|
+
type CodeNames = { [code: string]: { name: string, score: number, names: string[] } };
|
|
14
|
+
type CachedItem = { topology: any, nameIdx: NameCodes, codeIdx: CodeNames };
|
|
15
|
+
const _cachedRegion: { [id: string]: CachedItem } = {};
|
|
16
|
+
function cachedRegion(id: string): CachedItem {
|
|
17
|
+
if (!_cachedRegion[id]) {
|
|
18
|
+
_cachedRegion[id] = {
|
|
19
|
+
topology: undefined,
|
|
20
|
+
nameIdx: {},
|
|
21
|
+
codeIdx: {}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return _cachedRegion[id];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class Region extends World {
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
super();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected fetchTopo(regionID: string) {
|
|
34
|
+
if (cachedRegion(regionID).topology) {
|
|
35
|
+
return Promise.resolve(cachedRegion(regionID).topology);
|
|
36
|
+
}
|
|
37
|
+
return new Promise((resolve, reject) => {
|
|
38
|
+
d3Json(`${topoJsonFolder()}/${regionID}.json`, function (region) {
|
|
39
|
+
cachedRegion(regionID).topology = region;
|
|
40
|
+
resolve(region);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
protected fetchTopoIdx(regionID: string) {
|
|
46
|
+
for (const _key in cachedRegion(regionID).nameIdx) {
|
|
47
|
+
return Promise.resolve(cachedRegion(regionID).nameIdx);
|
|
48
|
+
}
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
d3Json(`${topoJsonFolder()}/${regionID}_idx.json`, function (index) {
|
|
51
|
+
const { nameIdx, codeIdx } = cachedRegion(regionID);
|
|
52
|
+
topo_indexes[regionID]?.forEach(level => {
|
|
53
|
+
for (const name in index[level]) {
|
|
54
|
+
const codes = index[level][name];
|
|
55
|
+
if (Array.isArray(codes)) {
|
|
56
|
+
if (!nameIdx[name]) {
|
|
57
|
+
nameIdx[name] = { code: undefined, codes: [] };
|
|
58
|
+
}
|
|
59
|
+
nameIdx[name].codes = nameIdx[name].codes.concat(codes);
|
|
60
|
+
if (codes.length === 1) {
|
|
61
|
+
nameIdx[name].code = nameIdx[name].codes[0];
|
|
62
|
+
}
|
|
63
|
+
codes.forEach(code => {
|
|
64
|
+
if (!codeIdx[code]) {
|
|
65
|
+
codeIdx[code] = { name: undefined, score: 9999, names: [] };
|
|
66
|
+
}
|
|
67
|
+
if (codes.length <= codeIdx[code].score) {
|
|
68
|
+
codeIdx[code].name = name;
|
|
69
|
+
codeIdx[code].score = codes.length;
|
|
70
|
+
}
|
|
71
|
+
codeIdx[code].names.push(name);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
resolve(nameIdx);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
updateDataMap(_?) {
|
|
82
|
+
const expandedRetVal = [];
|
|
83
|
+
const nameIdx = cachedRegion(this.region()).nameIdx;
|
|
84
|
+
_.forEach(row => {
|
|
85
|
+
const codes = nameIdx[row[0]]?.codes;
|
|
86
|
+
if (codes) {
|
|
87
|
+
codes?.forEach(code => {
|
|
88
|
+
expandedRetVal.push([code, row[1], row]);
|
|
89
|
+
});
|
|
90
|
+
} else {
|
|
91
|
+
expandedRetVal.push([row[0], row[1], row]);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return super.updateDataMap(expandedRetVal);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_prevRegion: string;
|
|
98
|
+
init(): Promise<void> {
|
|
99
|
+
const regionID = this.region();
|
|
100
|
+
if (!this._initPromise || this._prevRegion !== regionID) {
|
|
101
|
+
this._prevRegion = regionID;
|
|
102
|
+
this._initPromise = Promise.all([
|
|
103
|
+
this.fetchTopo(regionID),
|
|
104
|
+
this.fetchTopoIdx(regionID)
|
|
105
|
+
]).then(([region, index]: [any, any]) => {
|
|
106
|
+
this._features = topojson.feature(region, region.objects.PolbndA).features;
|
|
107
|
+
for (const key in this._features) {
|
|
108
|
+
const code = this._features[key].id || key;
|
|
109
|
+
this._features[key].properties.hpccID = code;
|
|
110
|
+
}
|
|
111
|
+
this.updateDataMap(this.data());
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return this._initPromise;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
tooltipHandler(l, featureID) {
|
|
118
|
+
const row = this._dataMap[featureID];
|
|
119
|
+
const codeIdx = cachedRegion(this.region()).codeIdx;
|
|
120
|
+
const value = row && row[1] || "";
|
|
121
|
+
const featureName = codeIdx[featureID]?.names.map(name => {
|
|
122
|
+
if (codeIdx[featureID]?.name === name) {
|
|
123
|
+
return `<u>${name}</u>`;
|
|
124
|
+
}
|
|
125
|
+
return name;
|
|
126
|
+
}).join(", ");
|
|
127
|
+
return this.tooltipText(this.rowToObj(row), `<b>${row && row[2][0] || featureName || featureID}</b>: ${value}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
Region.prototype._class += " map_Region";
|
|
131
|
+
|
|
132
|
+
export interface Region {
|
|
133
|
+
region(): string;
|
|
134
|
+
region(_: string): this;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
Region.prototype.publish("region", "GB", "set", "Region Data", ["AT", "BE", "BG", "BR", "CHLI", "CY", "CZ", "DE", "DK", "EE", "ES", "FI", "FR", "GB", "GE", "GR", "HR", "HU", "IE", "IS", "IT", "KS", "LT", "LU", "LV", "MD", "MK", "MT", "ND", "NL", "NO", "PL", "PT", "RO", "RS", "SE", "SI", "SK", "UA"]);
|
|
138
|
+
|