solid-map-gl 1.12.0 → 2.0.0
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/README.md +157 -30
- package/dist/index.d.ts +489 -0
- package/dist/index.js +11 -0
- package/dist/index.jsx +2320 -0
- package/package.json +46 -35
- package/dist/esm/index.js +0 -2
- package/dist/esm/index.js.map +0 -1
- package/dist/source/components/Atmosphere/index.jsx +0 -13
- package/dist/source/components/Camera/index.jsx +0 -108
- package/dist/source/components/Control/index.jsx +0 -33
- package/dist/source/components/Draw/drawingStyles.js +0 -225
- package/dist/source/components/Draw/index.jsx +0 -55
- package/dist/source/components/Draw/modes/index.js +0 -9
- package/dist/source/components/Draw/modes/line_string.js +0 -43
- package/dist/source/components/Draw/modes/measurements.js +0 -76
- package/dist/source/components/Draw/modes/multi_point.js +0 -37
- package/dist/source/components/Draw/modes/point.js +0 -25
- package/dist/source/components/Draw/modes/polygon.js +0 -25
- package/dist/source/components/Draw/modes/radius.js +0 -138
- package/dist/source/components/Draw/modes/rectangle.js +0 -118
- package/dist/source/components/Draw/modes/rectangle_assisted.js +0 -233
- package/dist/source/components/Image/index.jsx +0 -135
- package/dist/source/components/Layer/index.jsx +0 -125
- package/dist/source/components/Layer3D/index.jsx +0 -330
- package/dist/source/components/Light/index.jsx +0 -10
- package/dist/source/components/MapGL/index.jsx +0 -272
- package/dist/source/components/MapProvider/index.jsx +0 -9
- package/dist/source/components/Marker/index.jsx +0 -57
- package/dist/source/components/Popup/index.jsx +0 -38
- package/dist/source/components/Source/index.jsx +0 -89
- package/dist/source/components/Terrain/index.jsx +0 -30
- package/dist/source/events.js +0 -78
- package/dist/source/index.jsx +0 -14
- package/dist/source/mapStyles.js +0 -116
- package/dist/source/styles.js +0 -62
- package/dist/types/components/Atmosphere/index.d.ts +0 -8
- package/dist/types/components/Camera/index.d.ts +0 -54
- package/dist/types/components/Control/index.d.ts +0 -15
- package/dist/types/components/Draw/drawingStyles.d.ts +0 -20
- package/dist/types/components/Draw/index.d.ts +0 -16
- package/dist/types/components/Draw/modes/index.d.ts +0 -6
- package/dist/types/components/Draw/modes/line_string.d.ts +0 -2
- package/dist/types/components/Draw/modes/multi_point.d.ts +0 -2
- package/dist/types/components/Draw/modes/point.d.ts +0 -2
- package/dist/types/components/Draw/modes/polygon.d.ts +0 -2
- package/dist/types/components/Draw/modes/radius.d.ts +0 -2
- package/dist/types/components/Draw/modes/rectangle.d.ts +0 -2
- package/dist/types/components/Draw/modes/rectangle_assisted.d.ts +0 -18
- package/dist/types/components/Image/index.d.ts +0 -28
- package/dist/types/components/Layer/index.d.ts +0 -32
- package/dist/types/components/Layer3D/index.d.ts +0 -22
- package/dist/types/components/Light/index.d.ts +0 -8
- package/dist/types/components/MapGL/index.d.ts +0 -95
- package/dist/types/components/MapProvider/index.d.ts +0 -11
- package/dist/types/components/Marker/index.d.ts +0 -28
- package/dist/types/components/Popup/index.d.ts +0 -18
- package/dist/types/components/Source/index.d.ts +0 -13
- package/dist/types/components/Terrain/index.d.ts +0 -7
- package/dist/types/events.d.ts +0 -103
- package/dist/types/index.d.ts +0 -16
- package/dist/types/mapStyles.d.ts +0 -2
- package/dist/types/styles.d.ts +0 -2
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import MapboxDraw from "@mapbox/mapbox-gl-draw";
|
|
2
|
-
import { getArea, getLength } from "./measurements";
|
|
3
|
-
const RectangleMode = {
|
|
4
|
-
...MapboxDraw.modes.draw_line_string,
|
|
5
|
-
// When the mode starts this function will be called.
|
|
6
|
-
onSetup: function (opts) {
|
|
7
|
-
const props = MapboxDraw.modes.draw_line_string.onSetup.call(this, opts);
|
|
8
|
-
const rectangle = this.newFeature({
|
|
9
|
-
type: "Feature",
|
|
10
|
-
properties: {},
|
|
11
|
-
geometry: {
|
|
12
|
-
type: "Polygon",
|
|
13
|
-
coordinates: [[]],
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
this.addFeature(rectangle);
|
|
17
|
-
return { ...props, ...opts, rectangle };
|
|
18
|
-
},
|
|
19
|
-
// support mobile taps
|
|
20
|
-
onTap: function (state, e) {
|
|
21
|
-
// emulate 'move mouse' to update feature coords
|
|
22
|
-
if (state.startPoint)
|
|
23
|
-
this.onMouseMove(state, e);
|
|
24
|
-
// emulate onClick
|
|
25
|
-
this.onClick(state, e);
|
|
26
|
-
},
|
|
27
|
-
// Whenever a user clicks on the map, Draw will call `onClick`
|
|
28
|
-
onClick: function (state, e) {
|
|
29
|
-
if (state.startPoint &&
|
|
30
|
-
state.startPoint[0] !== e.lngLat.lng &&
|
|
31
|
-
state.startPoint[1] !== e.lngLat.lat) {
|
|
32
|
-
// if state.startPoint exist, means its second click
|
|
33
|
-
// change to simple_select mode
|
|
34
|
-
this.updateUIClasses({ mouse: "pointer" });
|
|
35
|
-
state.endPoint = [e.lngLat.lng, e.lngLat.lat];
|
|
36
|
-
this.changeMode("simple_select", { featuresId: state.rectangle.id });
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
// if its first click, save clicked point coords as starting for rectangle
|
|
40
|
-
state.startPoint = [e.lngLat.lng, e.lngLat.lat];
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
onMouseMove: function (state, e) {
|
|
44
|
-
// if startPoint, update the feature coordinates, using the bounding box concept
|
|
45
|
-
// we are simply using the startingPoint coordinates and the current Mouse Position
|
|
46
|
-
// coordinates to calculate the bounding box on the fly, which will be our rectangle
|
|
47
|
-
if (state.startPoint) {
|
|
48
|
-
state.rectangle.updateCoordinate("0.0", state.startPoint[0], state.startPoint[1]); //minX, minY - the starting point
|
|
49
|
-
state.rectangle.updateCoordinate("0.1", e.lngLat.lng, state.startPoint[1]); // maxX, minY
|
|
50
|
-
state.rectangle.updateCoordinate("0.2", e.lngLat.lng, e.lngLat.lat); // maxX, maxY
|
|
51
|
-
state.rectangle.updateCoordinate("0.3", state.startPoint[0], e.lngLat.lat); // minX,maxY
|
|
52
|
-
state.rectangle.updateCoordinate("0.4", state.startPoint[0], state.startPoint[1]); //minX,minY - ending point (equals to starting point)
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
// Whenever a user clicks on a key while focused on the map, it will be sent here
|
|
56
|
-
onKeyUp: function (state, e) {
|
|
57
|
-
if (e.keyCode === 27)
|
|
58
|
-
return this.changeMode("simple_select");
|
|
59
|
-
},
|
|
60
|
-
onStop: function (state) {
|
|
61
|
-
MapboxDraw.modes.draw_line_string.onStop.call(this, state);
|
|
62
|
-
// check to see if we've deleted this feature
|
|
63
|
-
if (this.getFeature(state.rectangle.id) === undefined)
|
|
64
|
-
return;
|
|
65
|
-
//remove last added coordinate
|
|
66
|
-
state.rectangle.removeCoordinate("0.4");
|
|
67
|
-
if (state.rectangle.isValid()) {
|
|
68
|
-
this.map.fire("draw.create", {
|
|
69
|
-
features: [state.rectangle.toGeoJSON()],
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
this.deleteFeature([state.rectangle.id], { silent: true });
|
|
74
|
-
this.changeMode("simple_select", {}, { silent: true });
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
toDisplayFeatures: function (state, geojson, display) {
|
|
78
|
-
console.log(state);
|
|
79
|
-
const isActivePolygon = geojson.properties.id === state.rectangle.id;
|
|
80
|
-
geojson.properties.active = isActivePolygon ? "true" : "false";
|
|
81
|
-
if (!isActivePolygon)
|
|
82
|
-
return display(geojson);
|
|
83
|
-
// Only render the rectangular polygon if it has the starting point
|
|
84
|
-
if (!state.startPoint)
|
|
85
|
-
return;
|
|
86
|
-
display(geojson);
|
|
87
|
-
// create custom feature for the current pointer position
|
|
88
|
-
if (state.showLength) {
|
|
89
|
-
display(getLength({
|
|
90
|
-
type: "Feature",
|
|
91
|
-
geometry: {
|
|
92
|
-
type: "LineString",
|
|
93
|
-
coordinates: [
|
|
94
|
-
geojson.geometry.coordinates[0][0],
|
|
95
|
-
geojson.geometry.coordinates[0][1],
|
|
96
|
-
],
|
|
97
|
-
},
|
|
98
|
-
}, { parent: state.rectangle.id, anchor: "bottom" }));
|
|
99
|
-
display(getLength({
|
|
100
|
-
type: "Feature",
|
|
101
|
-
geometry: {
|
|
102
|
-
type: "LineString",
|
|
103
|
-
coordinates: [
|
|
104
|
-
geojson.geometry.coordinates[0][1],
|
|
105
|
-
geojson.geometry.coordinates[0][2],
|
|
106
|
-
],
|
|
107
|
-
},
|
|
108
|
-
}, { parent: state.rectangle.id, anchor: "left" }));
|
|
109
|
-
}
|
|
110
|
-
state.showArea && display(getArea(geojson, { parent: state.rectangle.id }));
|
|
111
|
-
return null;
|
|
112
|
-
},
|
|
113
|
-
onTrash: function (state) {
|
|
114
|
-
this.deleteFeature([state.rectangle.id], { silent: true });
|
|
115
|
-
this.changeMode("simple_select");
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
export default RectangleMode;
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
const doubleClickZoom = {
|
|
2
|
-
enable: (ctx) => {
|
|
3
|
-
setTimeout(() => {
|
|
4
|
-
// First check we've got a map and some context.
|
|
5
|
-
if (!ctx.map ||
|
|
6
|
-
!ctx.map.doubleClickZoom ||
|
|
7
|
-
!ctx._ctx ||
|
|
8
|
-
!ctx._ctx.store ||
|
|
9
|
-
!ctx._ctx.store.getInitialConfigValue)
|
|
10
|
-
return;
|
|
11
|
-
if (!ctx._ctx.store.getInitialConfigValue("doubleClickZoom"))
|
|
12
|
-
return;
|
|
13
|
-
ctx.map.doubleClickZoom.enable();
|
|
14
|
-
}, 0);
|
|
15
|
-
},
|
|
16
|
-
disable(ctx) {
|
|
17
|
-
setTimeout(() => {
|
|
18
|
-
if (!ctx.map || !ctx.map.doubleClickZoom)
|
|
19
|
-
return;
|
|
20
|
-
ctx.map.doubleClickZoom.disable();
|
|
21
|
-
}, 0);
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
const RectangleAssistedMode = {
|
|
25
|
-
onSetup: function (opts) {
|
|
26
|
-
const rectangle = this.newFeature({
|
|
27
|
-
type: "Feature",
|
|
28
|
-
properties: {},
|
|
29
|
-
geometry: {
|
|
30
|
-
type: "Polygon",
|
|
31
|
-
coordinates: [[]],
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
this.addFeature(rectangle);
|
|
35
|
-
this.clearSelectedFeatures();
|
|
36
|
-
doubleClickZoom.disable(this);
|
|
37
|
-
this.updateUIClasses({
|
|
38
|
-
mouse: "add",
|
|
39
|
-
});
|
|
40
|
-
this.setActionableState({
|
|
41
|
-
trash: true,
|
|
42
|
-
});
|
|
43
|
-
return {
|
|
44
|
-
rectangle,
|
|
45
|
-
currentVertexPosition: 0,
|
|
46
|
-
};
|
|
47
|
-
},
|
|
48
|
-
onTap: function (state, e) {
|
|
49
|
-
this.onClick(state, e);
|
|
50
|
-
},
|
|
51
|
-
onClick: function (state, e) {
|
|
52
|
-
if (state.currentVertexPosition === 2) {
|
|
53
|
-
const getpXY3 = this.calculatepXY3(state, e, false);
|
|
54
|
-
if (getpXY3) {
|
|
55
|
-
state.rectangle.updateCoordinate(`0.${state.currentVertexPosition + 1}`, getpXY3[0], getpXY3[1]);
|
|
56
|
-
}
|
|
57
|
-
this.updateUIClasses({
|
|
58
|
-
mouse: "pointer",
|
|
59
|
-
});
|
|
60
|
-
return this.changeMode("simple_select", {
|
|
61
|
-
featuresId: state.rectangle.id,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
else {
|
|
65
|
-
state.rectangle.updateCoordinate(`0.${state.currentVertexPosition}`, e.lngLat.lng, e.lngLat.lat);
|
|
66
|
-
state.currentVertexPosition++;
|
|
67
|
-
state.rectangle.updateCoordinate(`0.${state.currentVertexPosition}`, e.lngLat.lng, e.lngLat.lat);
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
onMouseMove: function (state, e) {
|
|
71
|
-
state.rectangle.updateCoordinate("0." + state.currentVertexPosition, e.lngLat.lng, e.lngLat.lat);
|
|
72
|
-
if (state.currentVertexPosition && state.currentVertexPosition > 0) {
|
|
73
|
-
this.calculateOrientedAnglePolygon(state);
|
|
74
|
-
}
|
|
75
|
-
if (state.currentVertexPosition === 2) {
|
|
76
|
-
const getpXY3 = this.calculatepXY3(state, e, true);
|
|
77
|
-
if (getpXY3) {
|
|
78
|
-
state.rectangle.updateCoordinate("0." + (state.currentVertexPosition + 1), getpXY3[0], getpXY3[1]);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
deegrees2meters(px) {
|
|
83
|
-
//gist from https://gist.github.com/springmeyer/871897
|
|
84
|
-
const x = (px[0] * 20037508.34) / 180;
|
|
85
|
-
let y = Math.log(Math.tan(((90 + px[1]) * Math.PI) / 360)) / (Math.PI / 180);
|
|
86
|
-
y = (y * 20037508.34) / 180;
|
|
87
|
-
return [x, y];
|
|
88
|
-
},
|
|
89
|
-
meters2degress(px) {
|
|
90
|
-
//gist from https://gist.github.com/springmeyer/871897
|
|
91
|
-
const lon = (px[0] * 180) / 20037508.34;
|
|
92
|
-
const lat = (Math.atan(Math.exp((px[1] * Math.PI) / 20037508.34)) * 360) / Math.PI -
|
|
93
|
-
90;
|
|
94
|
-
return [lon, lat];
|
|
95
|
-
},
|
|
96
|
-
calculateOrientedAnglePolygon: function (state) {
|
|
97
|
-
const pXY0 = state.rectangle.getCoordinate("0.0");
|
|
98
|
-
const pXY0_3857 = this.deegrees2meters(pXY0);
|
|
99
|
-
const pXY1 = state.rectangle.getCoordinate("0.1");
|
|
100
|
-
const pXY1_3857 = this.deegrees2meters(pXY1);
|
|
101
|
-
const angleStdGraus = (Math.atan2(pXY1_3857[1] - pXY0_3857[1], pXY1_3857[0] - pXY0_3857[0]) *
|
|
102
|
-
180) /
|
|
103
|
-
Math.PI;
|
|
104
|
-
let angleSudGraus = -1.0 * (angleStdGraus + 90);
|
|
105
|
-
const angle = angleSudGraus < 0 ? angleSudGraus + 360 : angleSudGraus;
|
|
106
|
-
state.angle = parseFloat(angle.toFixed(2));
|
|
107
|
-
},
|
|
108
|
-
calculatepXY3: function (state, e, tmp) {
|
|
109
|
-
const pXY0 = state.rectangle.getCoordinate("0.0");
|
|
110
|
-
const pXY0_3857 = this.deegrees2meters(pXY0);
|
|
111
|
-
const pXY1 = state.rectangle.getCoordinate("0.1");
|
|
112
|
-
const pXY1_3857 = this.deegrees2meters(pXY1);
|
|
113
|
-
let pXY2_3857 = this.deegrees2meters([e.lngLat.lng, e.lngLat.lat]);
|
|
114
|
-
const mouse_3857 = this.deegrees2meters([e.lngLat.lng, e.lngLat.lat]);
|
|
115
|
-
if (pXY0_3857[0] === pXY1_3857[0]) {
|
|
116
|
-
pXY2_3857 = [mouse_3857[0], pXY1_3857[1]];
|
|
117
|
-
}
|
|
118
|
-
else if (pXY0_3857[1] === pXY1_3857[1]) {
|
|
119
|
-
pXY2_3857 = [pXY1_3857[0], mouse_3857[1]];
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
const vector1_3857 = (pXY1_3857[1] - pXY0_3857[1]) / (pXY1_3857[0] - pXY0_3857[0]);
|
|
123
|
-
const vector2_3857 = -1.0 / vector1_3857;
|
|
124
|
-
if (Math.abs(vector2_3857) < 1) {
|
|
125
|
-
pXY2_3857[1] =
|
|
126
|
-
vector2_3857 * (mouse_3857[0] - pXY1_3857[0]) + pXY1_3857[1];
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
pXY2_3857[0] =
|
|
130
|
-
pXY1_3857[0] + (pXY2_3857[1] - pXY1_3857[1]) / vector2_3857;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
const vector_3857 = [
|
|
134
|
-
pXY1_3857[0] - pXY0_3857[0],
|
|
135
|
-
pXY1_3857[1] - pXY0_3857[1],
|
|
136
|
-
];
|
|
137
|
-
const pXY3_3857 = [
|
|
138
|
-
pXY2_3857[0] - vector_3857[0],
|
|
139
|
-
pXY2_3857[1] - vector_3857[1],
|
|
140
|
-
];
|
|
141
|
-
const pXY2G = this.meters2degress(pXY2_3857);
|
|
142
|
-
const pXY3G = this.meters2degress(pXY3_3857);
|
|
143
|
-
state.rectangle.updateCoordinate("0.2", pXY2G[0], pXY2G[1]);
|
|
144
|
-
state.rectangle.updateCoordinate("0.3", pXY3G[0], pXY3G[1]);
|
|
145
|
-
return pXY3G;
|
|
146
|
-
},
|
|
147
|
-
onKeyUp: function (state, e) {
|
|
148
|
-
if (e.keyCode === 27)
|
|
149
|
-
return this.changeMode("simple_select");
|
|
150
|
-
},
|
|
151
|
-
onStop: function (state) {
|
|
152
|
-
doubleClickZoom.enable(this);
|
|
153
|
-
this.updateUIClasses({
|
|
154
|
-
mouse: "none",
|
|
155
|
-
});
|
|
156
|
-
this.activateUIButton();
|
|
157
|
-
// check to see if we've deleted this feature
|
|
158
|
-
if (this.getFeature(state.rectangle.id) === undefined)
|
|
159
|
-
return;
|
|
160
|
-
//remove last added coordinate
|
|
161
|
-
state.rectangle.removeCoordinate("0.4");
|
|
162
|
-
if (state.rectangle.isValid()) {
|
|
163
|
-
this.map.fire("draw.create", {
|
|
164
|
-
features: [state.rectangle.toGeoJSON()],
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
this.deleteFeature([state.rectangle.id], {
|
|
169
|
-
silent: true,
|
|
170
|
-
});
|
|
171
|
-
this.changeMode("simple_select", {}, {
|
|
172
|
-
silent: true,
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
toDisplayFeatures: function (state, geojson, display) {
|
|
177
|
-
const isActivePolygon = geojson.properties.id === state.rectangle.id;
|
|
178
|
-
geojson.properties.active = isActivePolygon ? "true" : "false";
|
|
179
|
-
geojson.properties.angle = state.angle;
|
|
180
|
-
geojson.angle = state.angle;
|
|
181
|
-
if (!isActivePolygon)
|
|
182
|
-
return display(geojson);
|
|
183
|
-
const coordinateCount = geojson.geometry.coordinates[0].length;
|
|
184
|
-
if (coordinateCount < 3) {
|
|
185
|
-
const coordinates = geojson.geometry.coordinates[0][0];
|
|
186
|
-
const vertexPoint = {
|
|
187
|
-
type: "Feature",
|
|
188
|
-
properties: geojson.properties,
|
|
189
|
-
angle: state.angle,
|
|
190
|
-
geometry: {
|
|
191
|
-
coordinates: geojson.geometry.coordinates[0][0],
|
|
192
|
-
type: "Point",
|
|
193
|
-
},
|
|
194
|
-
};
|
|
195
|
-
if (coordinates) {
|
|
196
|
-
display(vertexPoint);
|
|
197
|
-
}
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
if (coordinateCount >= 3 && coordinateCount <= 4) {
|
|
201
|
-
const lineCoordinates = [
|
|
202
|
-
[
|
|
203
|
-
geojson.geometry.coordinates[0][0][0],
|
|
204
|
-
geojson.geometry.coordinates[0][0][1],
|
|
205
|
-
],
|
|
206
|
-
[
|
|
207
|
-
geojson.geometry.coordinates[0][1][0],
|
|
208
|
-
geojson.geometry.coordinates[0][1][1],
|
|
209
|
-
],
|
|
210
|
-
];
|
|
211
|
-
display({
|
|
212
|
-
type: "Feature",
|
|
213
|
-
properties: geojson.properties,
|
|
214
|
-
angle: state.angle,
|
|
215
|
-
geometry: {
|
|
216
|
-
coordinates: lineCoordinates,
|
|
217
|
-
type: "LineString",
|
|
218
|
-
},
|
|
219
|
-
});
|
|
220
|
-
if (coordinateCount === 3) {
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return display(geojson);
|
|
225
|
-
},
|
|
226
|
-
onTrash: function (state) {
|
|
227
|
-
this.deleteFeature([state.rectangle.id], {
|
|
228
|
-
silent: true,
|
|
229
|
-
});
|
|
230
|
-
this.changeMode("simple_select");
|
|
231
|
-
},
|
|
232
|
-
};
|
|
233
|
-
export default RectangleAssistedMode;
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { onCleanup, createSignal, createEffect, untrack, } from 'solid-js';
|
|
2
|
-
import { useMapContext } from '../MapProvider';
|
|
3
|
-
const PATTERN = {
|
|
4
|
-
diagonal_l: { size: 20, path: 'M20 0 0 20M-10 10 10-10M10 30 30 10' },
|
|
5
|
-
diagonal_r: { size: 20, path: 'M0 0 20 20M30 10 10-10M10 30-10 10' },
|
|
6
|
-
horizontal: { size: 14, path: 'M7 0V20' },
|
|
7
|
-
vertical: { size: 14, path: 'M0 7H20' },
|
|
8
|
-
cross: { size: 18, path: 'M9 0V18M0 9H18' },
|
|
9
|
-
hash: { size: 30, path: 'M15 0 30 15 15 30 0 15Z' },
|
|
10
|
-
chevron_h: { size: 20, path: 'M-5 5 0 10 10 0 20 10 25 5M0 30 10 20 20 30' },
|
|
11
|
-
chevron_v: { size: 20, path: 'M5-5 10 0 0 10 10 20 5 25M25 15 20 10 25 5' },
|
|
12
|
-
square: { size: 20, path: 'M8 8H12V12H8Z', fill: true },
|
|
13
|
-
hex: { size: 50, path: 'M0 0V50L50 25ZM50 0V50L0 25ZM25 0V50' },
|
|
14
|
-
circle: {
|
|
15
|
-
size: 25,
|
|
16
|
-
path: 'M8 10A2.5 2.5 0 118.01 10M18 15A2.5 2.5 0 1018.01 15',
|
|
17
|
-
fill: true,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
export const patternList = Object.keys(PATTERN);
|
|
21
|
-
export const MGL_Image = props => {
|
|
22
|
-
const [ctx] = useMapContext();
|
|
23
|
-
const [size, setSize] = createSignal({ width: 0, height: 0 });
|
|
24
|
-
const debug = (text, value) => {
|
|
25
|
-
ctx.map.debug &&
|
|
26
|
-
console.debug('%c[MapGL]', 'color: #10b981', text, value || '');
|
|
27
|
-
};
|
|
28
|
-
// Remove Image
|
|
29
|
-
onCleanup(() => {
|
|
30
|
-
ctx.map?.hasImage(props.id) && ctx.map?.removeImage(props.id);
|
|
31
|
-
debug('Remove Image:', props.id);
|
|
32
|
-
});
|
|
33
|
-
// Add or Update Image
|
|
34
|
-
createEffect(() => {
|
|
35
|
-
if (!props.id)
|
|
36
|
-
throw new Error('Image - ID is required');
|
|
37
|
-
if (!props.source && !props.pattern)
|
|
38
|
-
throw new Error('Image - Image or Pattern is required');
|
|
39
|
-
const ops = props.pattern
|
|
40
|
-
? { pixelRatio: 2, ...props.options }
|
|
41
|
-
: props.options;
|
|
42
|
-
_loadImage(props.source || _createPattern(props.pattern), data => {
|
|
43
|
-
const { width, height } = data;
|
|
44
|
-
if (ctx.map && !ctx.map.hasImage(props.id))
|
|
45
|
-
ctx.map.addImage(props.id, data, ops);
|
|
46
|
-
if (!props.pattern &&
|
|
47
|
-
untrack(() => width === size().width && height === size().height)) {
|
|
48
|
-
ctx.map.updateImage(props.id, data);
|
|
49
|
-
ctx.map.triggerRepaint();
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
ctx.map.removeImage(props.id);
|
|
53
|
-
ctx.map.addImage(props.id, data, ops);
|
|
54
|
-
}
|
|
55
|
-
setSize({ width, height });
|
|
56
|
-
debug('Add Image:', props.id);
|
|
57
|
-
ctx.map.on('style.load', () => {
|
|
58
|
-
if (ctx.map.hasImage(props.id))
|
|
59
|
-
return;
|
|
60
|
-
ctx.map.addImage(props.id, data, ops);
|
|
61
|
-
debug('Re-Add Image:', props.id);
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
// Load Image / SVG
|
|
66
|
-
const _loadImage = (image, callback) => {
|
|
67
|
-
if (typeof image == 'string' && image?.trimStart().startsWith('<svg')) {
|
|
68
|
-
image = new DOMParser().parseFromString(image, 'image/svg+xml')
|
|
69
|
-
.childNodes[0];
|
|
70
|
-
}
|
|
71
|
-
if (image instanceof SVGElement) {
|
|
72
|
-
props.options?.fill && image.setAttribute('fill', props.options.fill);
|
|
73
|
-
props.options?.stroke &&
|
|
74
|
-
image.setAttribute('stroke', props.options.stroke);
|
|
75
|
-
image = new XMLSerializer().serializeToString(image);
|
|
76
|
-
}
|
|
77
|
-
if (typeof image !== 'string')
|
|
78
|
-
return callback(image);
|
|
79
|
-
ctx.map.loadImage(image, async (error, imageData) => {
|
|
80
|
-
if (error) {
|
|
81
|
-
if (typeof image == 'string' && image?.trimEnd().endsWith('.svg')) {
|
|
82
|
-
image = await (await fetch(image)).text();
|
|
83
|
-
image = new DOMParser().parseFromString(image, 'image/svg+xml')
|
|
84
|
-
.childNodes[0];
|
|
85
|
-
image.setAttribute('fill', props.options.fill);
|
|
86
|
-
image.setAttribute('stroke', props.options.stroke);
|
|
87
|
-
image.setAttribute('transform', props.options.transform);
|
|
88
|
-
image = new XMLSerializer().serializeToString(image);
|
|
89
|
-
}
|
|
90
|
-
const img = new Image();
|
|
91
|
-
img.crossOrigin = 'Anonymous';
|
|
92
|
-
img.onload = () => {
|
|
93
|
-
const canvas = document.createElement('canvas');
|
|
94
|
-
canvas.width = Math.max(img.width, 50);
|
|
95
|
-
canvas.height = Math.max(img.height, 50);
|
|
96
|
-
const ctx = canvas.getContext('2d');
|
|
97
|
-
ctx.imageSmoothingEnabled = true;
|
|
98
|
-
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
99
|
-
return callback(ctx.getImageData(0, 0, canvas.width, canvas.height));
|
|
100
|
-
};
|
|
101
|
-
img.src = image.trimStart().startsWith('<svg')
|
|
102
|
-
? 'data:image/svg+xml;charset=utf-8,' + image
|
|
103
|
-
: image;
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
return callback(imageData);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
const _createPattern = pattern => {
|
|
111
|
-
const p = PATTERN[pattern.type];
|
|
112
|
-
return {
|
|
113
|
-
width: p.size,
|
|
114
|
-
height: p.size,
|
|
115
|
-
data: new Uint8Array(p.size * p.size * 4),
|
|
116
|
-
onAdd: function () {
|
|
117
|
-
let canvas = document.createElement('canvas');
|
|
118
|
-
canvas.width = canvas.height = p.size;
|
|
119
|
-
this.ctx = canvas.getContext('2d', { willReadFrequently: true });
|
|
120
|
-
},
|
|
121
|
-
render: function () {
|
|
122
|
-
this.ctx.fillStyle = pattern.background || 'transparent';
|
|
123
|
-
this.ctx.fillRect(0, 0, this.width, this.height);
|
|
124
|
-
this.ctx.strokeStyle = this.ctx.fillStyle = pattern.color || 'black';
|
|
125
|
-
this.ctx.lineWidth = pattern.lineWith || 1;
|
|
126
|
-
this.ctx.stroke(new Path2D(p.path));
|
|
127
|
-
if (p.fill)
|
|
128
|
-
this.ctx.fill(new Path2D(p.path));
|
|
129
|
-
this.data = this.ctx.getImageData(0, 0, this.width, this.height).data;
|
|
130
|
-
return true;
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
};
|
|
134
|
-
return null;
|
|
135
|
-
};
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { onCleanup, createEffect, createUniqueId } from "solid-js";
|
|
2
|
-
import { useMapContext } from "../MapProvider";
|
|
3
|
-
import { useSourceId } from "../Source";
|
|
4
|
-
import { layerEvents } from "../../events";
|
|
5
|
-
import { baseStyle, layoutStyles } from "../../styles";
|
|
6
|
-
const diff = (newProps = {}, prevProps = {}) => {
|
|
7
|
-
const keys = new Set([...Object.keys(newProps), ...Object.keys(prevProps)]);
|
|
8
|
-
return [...keys].reduce((acc, key) => {
|
|
9
|
-
const value = newProps[key];
|
|
10
|
-
if (value !== prevProps[key]) {
|
|
11
|
-
acc.push([key, value]);
|
|
12
|
-
}
|
|
13
|
-
return acc;
|
|
14
|
-
}, []);
|
|
15
|
-
};
|
|
16
|
-
const newKey = (key, type) => (key.startsWith(type) || key.startsWith("icon") || key.startsWith("text")
|
|
17
|
-
? ""
|
|
18
|
-
: type + "-") + key.replace(/[A-Z]/g, (s) => "-" + s.toLowerCase());
|
|
19
|
-
const updateStyle = (oldStyle) => {
|
|
20
|
-
if (!oldStyle)
|
|
21
|
-
return;
|
|
22
|
-
let layout = {};
|
|
23
|
-
let paint = {};
|
|
24
|
-
let style = {};
|
|
25
|
-
Object.entries(oldStyle).forEach(([key, value]) => {
|
|
26
|
-
if (baseStyle.includes(key))
|
|
27
|
-
style[key] = value;
|
|
28
|
-
else {
|
|
29
|
-
const nk = newKey(key, oldStyle.type);
|
|
30
|
-
layoutStyles.includes(nk) ? (layout[nk] = value) : (paint[nk] = value);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
if (oldStyle.paint)
|
|
34
|
-
Object.entries(oldStyle.paint).forEach(([key, value]) => (paint[newKey(key, oldStyle.type)] = value));
|
|
35
|
-
if (oldStyle.layout)
|
|
36
|
-
Object.entries(oldStyle.layout).forEach(([key, value]) => (layout[newKey(key, oldStyle.type)] = value));
|
|
37
|
-
return { ...style, paint, layout };
|
|
38
|
-
};
|
|
39
|
-
export const Layer = (props) => {
|
|
40
|
-
const [ctx] = useMapContext();
|
|
41
|
-
const sourceId = props.sourceId || props.style?.source || useSourceId();
|
|
42
|
-
const layerId = props.id || props.customLayer?.id || createUniqueId();
|
|
43
|
-
const debug = (text, value) => {
|
|
44
|
-
(ctx.map.debug || ctx.map.debugEvents) &&
|
|
45
|
-
console.debug("%c[MapGL]", "color: #10b981", text, value || "");
|
|
46
|
-
};
|
|
47
|
-
// Add Layer
|
|
48
|
-
ctx.map.addLayer(props.customLayer || {
|
|
49
|
-
...updateStyle(props.style),
|
|
50
|
-
id: layerId,
|
|
51
|
-
source: sourceId,
|
|
52
|
-
slot: props.slot || "",
|
|
53
|
-
metadata: {
|
|
54
|
-
smg: { beforeType: props.beforeType, beforeId: props.beforeId },
|
|
55
|
-
},
|
|
56
|
-
}, props.beforeType
|
|
57
|
-
? ctx.map.getStyle().layers.find((l) => l.type === props.beforeType)?.id
|
|
58
|
-
: props.beforeId);
|
|
59
|
-
ctx.map.layerIdList.push(layerId);
|
|
60
|
-
if (props.customLayer)
|
|
61
|
-
ctx.map.fire("load");
|
|
62
|
-
debug("Add Layer:", layerId);
|
|
63
|
-
// Hook up events
|
|
64
|
-
layerEvents.forEach((item) => {
|
|
65
|
-
if (props[item]) {
|
|
66
|
-
const event = item.slice(2).toLowerCase();
|
|
67
|
-
ctx.map.on(event, layerId, (evt) => {
|
|
68
|
-
evt.clickOnLayer = true;
|
|
69
|
-
props[item](evt);
|
|
70
|
-
ctx.map.debugEvent &&
|
|
71
|
-
debug(`Layer '${event}' event on '${layerId}':`, evt);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
// Update Style
|
|
76
|
-
createEffect((prev) => {
|
|
77
|
-
const style = updateStyle(props.style);
|
|
78
|
-
if (style === prev)
|
|
79
|
-
return;
|
|
80
|
-
if (style.layout !== prev?.layout)
|
|
81
|
-
diff(style.layout, prev?.layout).forEach(([key, value]) => ctx.map.setLayoutProperty(layerId, key, value, { validate: false }));
|
|
82
|
-
if (style.paint !== prev?.paint)
|
|
83
|
-
diff(style.paint, prev?.paint).forEach(([key, value]) => ctx.map.setPaintProperty(layerId, key, value, { validate: false }));
|
|
84
|
-
if (style.minzoom !== prev?.minzoom || style.maxzoom !== prev?.maxzoom)
|
|
85
|
-
ctx.map.setLayerZoomRange(layerId, style.minzoom, style.maxzoom);
|
|
86
|
-
if (style.filter !== prev?.filter)
|
|
87
|
-
ctx.map.setFilter(layerId, style.filter, { validate: false });
|
|
88
|
-
debug("Update Layer Style:", layerId);
|
|
89
|
-
return style;
|
|
90
|
-
}, updateStyle(props.style));
|
|
91
|
-
// Update Visibility
|
|
92
|
-
createEffect((prev) => {
|
|
93
|
-
if (props.visible === prev)
|
|
94
|
-
return;
|
|
95
|
-
ctx.map.setLayoutProperty(layerId, "visibility", props.visible ? "visible" : "none", { validate: false });
|
|
96
|
-
debug(`Update Visibility (${layerId}):`, props.visible.toString());
|
|
97
|
-
return props.visible;
|
|
98
|
-
}, props.visible);
|
|
99
|
-
// Update Filter
|
|
100
|
-
createEffect(async () => {
|
|
101
|
-
if (!props.filter)
|
|
102
|
-
return;
|
|
103
|
-
!ctx.map.isStyleLoaded() && (await ctx.map.once("styledata"));
|
|
104
|
-
ctx.map.setFilter(layerId, props.filter);
|
|
105
|
-
debug(`Update Filter (${layerId}):`, props.filter);
|
|
106
|
-
});
|
|
107
|
-
// Update Feature State
|
|
108
|
-
createEffect(async () => {
|
|
109
|
-
if (!props.featureState || props.featureState.id === null)
|
|
110
|
-
return;
|
|
111
|
-
!ctx.map.isStyleLoaded() && (await ctx.map.once("styledata"));
|
|
112
|
-
ctx.map.removeFeatureState({
|
|
113
|
-
source: sourceId,
|
|
114
|
-
sourceLayer: props.style["source-layer"],
|
|
115
|
-
});
|
|
116
|
-
ctx.map.setFeatureState({
|
|
117
|
-
source: sourceId,
|
|
118
|
-
sourceLayer: props.style["source-layer"],
|
|
119
|
-
id: props.featureState.id,
|
|
120
|
-
}, props.featureState.state);
|
|
121
|
-
});
|
|
122
|
-
//Remove Layer
|
|
123
|
-
onCleanup(() => ctx.map?.getLayer(layerId) && ctx.map?.removeLayer(layerId));
|
|
124
|
-
return props.children;
|
|
125
|
-
};
|