@hzab/map-combine 0.4.2-alpha.7 → 0.4.2-alpha.8

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.
@@ -1,363 +1,363 @@
1
- import { ReactElement } from "react";
2
- import { MapElement, MapElementOption } from "./MapElement";
3
- import Eventful from "zrender/lib/core/Eventful";
4
- import { MapCombine } from "./MapCombine";
5
- import ReactDOM from "react-dom";
6
- import { ContextMenuItem } from "./ContextMenu";
7
-
8
- export interface ReactPointOption<K> extends MapElementOption {
9
- show: boolean;
10
- coordinates?: number[];
11
- silent: boolean;
12
- element: (props: K) => ReactElement;
13
- center: number[];
14
- rotation: number;
15
- editable: boolean;
16
- props: K;
17
- menu?: ContextMenuItem[];
18
- }
19
-
20
- export class ReactPoint<K = undefined> extends MapElement<ReactPointOption<K>> {
21
- type: "ReactPoint";
22
- event = new Eventful<{
23
- "data-loaded": () => void;
24
- "data-update": () => void;
25
- "pointer-in": () => void;
26
- "pointer-out": () => void;
27
- "left-click": () => void;
28
- "right-click": () => void;
29
- update: (keys: Set<string>) => void;
30
- destroy: () => void;
31
- }>();
32
-
33
- get show() {
34
- return this._option.show;
35
- }
36
-
37
- set show(val) {
38
- if (this._option.show != val) {
39
- this._option.show = val;
40
- this._update("show");
41
- }
42
- }
43
-
44
- get menu() {
45
- return this._option.menu;
46
- }
47
-
48
- set menu(val) {
49
- this._option.menu = val;
50
- }
51
-
52
- get props() {
53
- return this._option.props;
54
- }
55
-
56
- set props(val) {
57
- if (this._option.props != val) {
58
- this._option.props = val;
59
- this._update("props");
60
- }
61
- }
62
-
63
- get silent() {
64
- return this._option.silent;
65
- }
66
-
67
- set silent(val) {
68
- if (this._option.silent != val) {
69
- this._option.silent = val;
70
- this._update("silent");
71
- }
72
- }
73
-
74
- get editable() {
75
- return this._option.editable;
76
- }
77
-
78
- set editable(val) {
79
- if (this._option.editable != val) {
80
- this._option.editable = val;
81
- this._update("editable");
82
- }
83
- }
84
-
85
- get coordinates() {
86
- return this._option.coordinates;
87
- }
88
-
89
- set coordinates(val) {
90
- if (this._option.coordinates != val) {
91
- this._option.coordinates = val;
92
- this._update("coordinates");
93
- }
94
- }
95
-
96
- get center() {
97
- return this._option.center;
98
- }
99
-
100
- set center(val) {
101
- if (this._option.center != val) {
102
- this._option.center = val;
103
- this._update("center");
104
- }
105
- }
106
-
107
- get rotation() {
108
- return this._option.rotation;
109
- }
110
-
111
- set rotation(val) {
112
- if (this._option.rotation != val) {
113
- this._option.rotation = val;
114
- this._update("rotation");
115
- }
116
- }
117
-
118
- get element() {
119
- return this._option.element;
120
- }
121
-
122
- set element(val) {
123
- if (this._option.element != val) {
124
- this._option.element = val;
125
- this._update("element");
126
- }
127
- }
128
-
129
- constructor(map: MapCombine, option: Partial<ReactPointOption<K>> = {}) {
130
- super(map, Object.assign({ ...ReactPoint.option }, option));
131
- }
132
-
133
- static option: ReactPointOption<undefined> = {
134
- name: "点",
135
- show: true,
136
- editable: false,
137
- center: [0.5, 0.5],
138
- rotation: 0,
139
- props: undefined,
140
- silent: false,
141
- element: () => (
142
- <div
143
- style={{
144
- backgroundColor: "#43F655",
145
- width: "16px",
146
- height: "16px",
147
- }}
148
- ></div>
149
- ),
150
- };
151
-
152
- private _needUpdate?: Set<string>;
153
- private _update(key: string) {
154
- if (this._needUpdate) {
155
- this._needUpdate.add(key);
156
- } else {
157
- this._needUpdate = new Set([key]);
158
- setTimeout(() => {
159
- this.event.trigger("update", this._needUpdate);
160
- this._needUpdate = undefined;
161
- });
162
- }
163
- }
164
-
165
- protected _onDestroy(): void {
166
- this.event.trigger("destroy");
167
- }
168
- }
169
-
170
- export function drawReactPoint(map: MapCombine, point: ReactPoint<unknown>) {
171
- const { event, htmllayer } = map;
172
- /** 当前点位的状态 0:初始态 1:编辑态 2:显示态 3:拖动态 */
173
- let status = 0;
174
- let skip = 0;
175
-
176
- const root = document.createElement("div");
177
- root.style.transform = `translate(-${point.center[0] * 100}%,-${point.center[1] * 100}%) rotateZ(${
178
- point.rotation
179
- }deg)`;
180
- root.style.transformOrigin = `${point.center[0] * 100}% ${point.center[1] * 100}%`;
181
- root.style.position = "absolute";
182
- root.style.visibility = point.show ? "visible" : "hidden";
183
- root.style.pointerEvents = point.silent ? "none" : "all";
184
- root.style.userSelect = "none";
185
- root.addEventListener("pointerenter", () => {
186
- status == 2 && point.event.trigger("pointer-in");
187
- });
188
- root.addEventListener("pointerleave", () => {
189
- status == 2 && point.event.trigger("pointer-out");
190
- });
191
- root.addEventListener("click", () => {
192
- status == 2 && point.event.trigger("left-click");
193
- });
194
- root.addEventListener("contextmenu", (e) => {
195
- // e.stopPropagation()
196
- e.preventDefault();
197
- if (point.menu) {
198
- map.menu.show(point.menu);
199
- }
200
- status == 2 && point.event.trigger("right-click");
201
- });
202
- ReactDOM.render(point.element(point.props), root);
203
- let delay = 0;
204
-
205
- root.addEventListener("pointerdown", () => {
206
- if (point.editable && status == 2) {
207
- delay = window.setTimeout(() => {
208
- delay = 0;
209
- status = 3;
210
- map.moveable = false;
211
- root.style.pointerEvents = "none";
212
- }, 300);
213
- }
214
- });
215
- if (point.coordinates) {
216
- status = 2;
217
- const p = map.geographyTcanvas(point.coordinates);
218
- root.style.left = `${p[0]}px`;
219
- root.style.top = `${p[1]}px`;
220
- htmllayer.appendChild(root);
221
- setTimeout(() => {
222
- point.event.trigger("data-loaded");
223
- });
224
- }
225
-
226
- const onViewChange = () => {
227
- if (point.coordinates) {
228
- const p = map.geographyTcanvas(point.coordinates);
229
- root.style.left = `${p[0]}px`;
230
- root.style.top = `${p[1]}px`;
231
- root.style.zIndex = `${point.coordinates[2] ?? ""}`;
232
- }
233
- };
234
-
235
- const onUpdate = (e: Set<string>) => {
236
- if (skip) {
237
- skip--;
238
- return;
239
- }
240
- const keys = new Set();
241
- e.forEach((key) => {
242
- switch (key) {
243
- case "show":
244
- root.style.visibility = point.show ? "visible" : "hidden";
245
- break;
246
- case "editable":
247
- break;
248
- case "props":
249
- keys.add("dom");
250
- break;
251
- case "element":
252
- keys.add("dom");
253
- break;
254
- case "coordinates":
255
- if (point.coordinates) {
256
- const p = map.geographyTcanvas(point.coordinates);
257
- root.style.left = `${p[0]}px`;
258
- root.style.top = `${p[1]}px`;
259
- root.style.zIndex = `${point.coordinates[2] ?? ""}`;
260
- switch (status) {
261
- case 0:
262
- htmllayer.appendChild(root);
263
- status = 2;
264
- break;
265
- case 1:
266
- status = 2;
267
- break;
268
- }
269
- } else {
270
- root.remove();
271
- status = 0;
272
- }
273
-
274
- break;
275
-
276
- case "center":
277
- keys.add("transform");
278
- break;
279
- case "rotation":
280
- keys.add("transform");
281
- break;
282
- default:
283
- throw new Error(`${key} 还不支持修改`);
284
- }
285
- });
286
-
287
- keys.forEach((e) => {
288
- switch (e) {
289
- case "transform":
290
- root.style.transform = `translate(-${point.center[0] * 100}%,-${point.center[1] * 100}%) rotateZ(${
291
- point.rotation
292
- }deg)`;
293
- root.style.transformOrigin = `${point.center[0] * 100}% ${point.center[1] * 100}%`;
294
- break;
295
- case "dom":
296
- ReactDOM.render(point.element(point.props), root);
297
- break;
298
- }
299
- });
300
- };
301
-
302
- const onMouseMove = () => {
303
- if (delay) {
304
- clearTimeout(delay);
305
- delay = 0;
306
- }
307
- switch (status) {
308
- case 0:
309
- status = 1;
310
- root.style.left = `${event.canvas[0]}px`;
311
- root.style.top = `${event.canvas[1]}px`;
312
- htmllayer.appendChild(root);
313
- break;
314
- case 1:
315
- case 3:
316
- root.style.left = `${event.canvas[0]}px`;
317
- root.style.top = `${event.canvas[1]}px`;
318
- break;
319
- }
320
- };
321
-
322
- const onClick = () => {
323
- if (status == 1) {
324
- status = 2;
325
- skip++;
326
- point.coordinates = event.geography;
327
- point.event.trigger("data-loaded");
328
- }
329
- };
330
-
331
- const onPointerUp = () => {
332
- if (delay) {
333
- clearTimeout(delay);
334
- delay = 0;
335
- }
336
- if (point.editable && status == 3) {
337
- status = 2;
338
- map.moveable = true;
339
- root.style.pointerEvents = point.silent ? "none" : "all";
340
- skip++;
341
- point.coordinates = event.geography;
342
- point.event.trigger("data-update");
343
- }
344
- };
345
-
346
- const onDestroy = () => {
347
- root.remove();
348
- ReactDOM.unmountComponentAtNode(root);
349
- event.off("view-change", onViewChange);
350
- event.off("pointer-move", onMouseMove);
351
- event.off("left-click", onClick);
352
- event.off("pointer-up", onPointerUp);
353
- point.event.off("update", onUpdate);
354
- point.event.off("destroy", onDestroy);
355
- };
356
-
357
- event.on("view-change", onViewChange);
358
- event.on("pointer-move", onMouseMove);
359
- event.on("left-click", onClick);
360
- event.on("pointer-up", onPointerUp);
361
- point.event.on("update", onUpdate);
362
- point.event.on("destroy", onDestroy);
363
- }
1
+ import { ReactElement } from "react";
2
+ import { MapElement, MapElementOption } from "./MapElement";
3
+ import Eventful from "zrender/lib/core/Eventful";
4
+ import { MapCombine } from "./MapCombine";
5
+ import ReactDOM from "react-dom";
6
+ import { ContextMenuItem } from "./ContextMenu";
7
+
8
+ export interface ReactPointOption<K> extends MapElementOption {
9
+ show: boolean;
10
+ coordinates?: number[];
11
+ silent: boolean;
12
+ element: (props: K) => ReactElement;
13
+ center: number[];
14
+ rotation: number;
15
+ editable: boolean;
16
+ props: K;
17
+ menu?: ContextMenuItem[];
18
+ }
19
+
20
+ export class ReactPoint<K = undefined> extends MapElement<ReactPointOption<K>> {
21
+ type: "ReactPoint";
22
+ event = new Eventful<{
23
+ "data-loaded": () => void;
24
+ "data-update": () => void;
25
+ "pointer-in": () => void;
26
+ "pointer-out": () => void;
27
+ "left-click": () => void;
28
+ "right-click": () => void;
29
+ update: (keys: Set<string>) => void;
30
+ destroy: () => void;
31
+ }>();
32
+
33
+ get show() {
34
+ return this._option.show;
35
+ }
36
+
37
+ set show(val) {
38
+ if (this._option.show != val) {
39
+ this._option.show = val;
40
+ this._update("show");
41
+ }
42
+ }
43
+
44
+ get menu() {
45
+ return this._option.menu;
46
+ }
47
+
48
+ set menu(val) {
49
+ this._option.menu = val;
50
+ }
51
+
52
+ get props() {
53
+ return this._option.props;
54
+ }
55
+
56
+ set props(val) {
57
+ if (this._option.props != val) {
58
+ this._option.props = val;
59
+ this._update("props");
60
+ }
61
+ }
62
+
63
+ get silent() {
64
+ return this._option.silent;
65
+ }
66
+
67
+ set silent(val) {
68
+ if (this._option.silent != val) {
69
+ this._option.silent = val;
70
+ this._update("silent");
71
+ }
72
+ }
73
+
74
+ get editable() {
75
+ return this._option.editable;
76
+ }
77
+
78
+ set editable(val) {
79
+ if (this._option.editable != val) {
80
+ this._option.editable = val;
81
+ this._update("editable");
82
+ }
83
+ }
84
+
85
+ get coordinates() {
86
+ return this._option.coordinates;
87
+ }
88
+
89
+ set coordinates(val) {
90
+ if (this._option.coordinates != val) {
91
+ this._option.coordinates = val;
92
+ this._update("coordinates");
93
+ }
94
+ }
95
+
96
+ get center() {
97
+ return this._option.center;
98
+ }
99
+
100
+ set center(val) {
101
+ if (this._option.center != val) {
102
+ this._option.center = val;
103
+ this._update("center");
104
+ }
105
+ }
106
+
107
+ get rotation() {
108
+ return this._option.rotation;
109
+ }
110
+
111
+ set rotation(val) {
112
+ if (this._option.rotation != val) {
113
+ this._option.rotation = val;
114
+ this._update("rotation");
115
+ }
116
+ }
117
+
118
+ get element() {
119
+ return this._option.element;
120
+ }
121
+
122
+ set element(val) {
123
+ if (this._option.element != val) {
124
+ this._option.element = val;
125
+ this._update("element");
126
+ }
127
+ }
128
+
129
+ constructor(map: MapCombine, option: Partial<ReactPointOption<K>> = {}) {
130
+ super(map, Object.assign({ ...ReactPoint.option }, option));
131
+ }
132
+
133
+ static option: ReactPointOption<undefined> = {
134
+ name: "点",
135
+ show: true,
136
+ editable: false,
137
+ center: [0.5, 0.5],
138
+ rotation: 0,
139
+ props: undefined,
140
+ silent: false,
141
+ element: () => (
142
+ <div
143
+ style={{
144
+ backgroundColor: "#43F655",
145
+ width: "16px",
146
+ height: "16px",
147
+ }}
148
+ ></div>
149
+ ),
150
+ };
151
+
152
+ private _needUpdate?: Set<string>;
153
+ private _update(key: string) {
154
+ if (this._needUpdate) {
155
+ this._needUpdate.add(key);
156
+ } else {
157
+ this._needUpdate = new Set([key]);
158
+ setTimeout(() => {
159
+ this.event.trigger("update", this._needUpdate);
160
+ this._needUpdate = undefined;
161
+ });
162
+ }
163
+ }
164
+
165
+ protected _onDestroy(): void {
166
+ this.event.trigger("destroy");
167
+ }
168
+ }
169
+
170
+ export function drawReactPoint(map: MapCombine, point: ReactPoint<unknown>) {
171
+ const { event, htmllayer } = map;
172
+ /** 当前点位的状态 0:初始态 1:编辑态 2:显示态 3:拖动态 */
173
+ let status = 0;
174
+ let skip = 0;
175
+
176
+ const root = document.createElement("div");
177
+ root.style.transform = `translate(-${point.center[0] * 100}%,-${point.center[1] * 100}%) rotateZ(${
178
+ point.rotation
179
+ }deg)`;
180
+ root.style.transformOrigin = `${point.center[0] * 100}% ${point.center[1] * 100}%`;
181
+ root.style.position = "absolute";
182
+ root.style.visibility = point.show ? "visible" : "hidden";
183
+ root.style.pointerEvents = point.silent ? "none" : "all";
184
+ root.style.userSelect = "none";
185
+ root.addEventListener("pointerenter", () => {
186
+ status == 2 && point.event.trigger("pointer-in");
187
+ });
188
+ root.addEventListener("pointerleave", () => {
189
+ status == 2 && point.event.trigger("pointer-out");
190
+ });
191
+ root.addEventListener("click", () => {
192
+ status == 2 && point.event.trigger("left-click");
193
+ });
194
+ root.addEventListener("contextmenu", (e) => {
195
+ // e.stopPropagation()
196
+ e.preventDefault();
197
+ if (point.menu) {
198
+ map.menu.show(point.menu);
199
+ }
200
+ status == 2 && point.event.trigger("right-click");
201
+ });
202
+ ReactDOM.render(point.element(point.props), root);
203
+ let delay = 0;
204
+
205
+ root.addEventListener("pointerdown", () => {
206
+ if (point.editable && status == 2) {
207
+ delay = window.setTimeout(() => {
208
+ delay = 0;
209
+ status = 3;
210
+ map.moveable = false;
211
+ root.style.pointerEvents = "none";
212
+ }, 300);
213
+ }
214
+ });
215
+ if (point.coordinates) {
216
+ status = 2;
217
+ const p = map.geographyTcanvas(point.coordinates);
218
+ root.style.left = `${p[0]}px`;
219
+ root.style.top = `${p[1]}px`;
220
+ htmllayer.appendChild(root);
221
+ setTimeout(() => {
222
+ point.event.trigger("data-loaded");
223
+ });
224
+ }
225
+
226
+ const onViewChange = () => {
227
+ if (point.coordinates) {
228
+ const p = map.geographyTcanvas(point.coordinates);
229
+ root.style.left = `${p[0]}px`;
230
+ root.style.top = `${p[1]}px`;
231
+ root.style.zIndex = `${point.coordinates[2] ?? ""}`;
232
+ }
233
+ };
234
+
235
+ const onUpdate = (e: Set<string>) => {
236
+ if (skip) {
237
+ skip--;
238
+ return;
239
+ }
240
+ const keys = new Set();
241
+ e.forEach((key) => {
242
+ switch (key) {
243
+ case "show":
244
+ root.style.visibility = point.show ? "visible" : "hidden";
245
+ break;
246
+ case "editable":
247
+ break;
248
+ case "props":
249
+ keys.add("dom");
250
+ break;
251
+ case "element":
252
+ keys.add("dom");
253
+ break;
254
+ case "coordinates":
255
+ if (point.coordinates) {
256
+ const p = map.geographyTcanvas(point.coordinates);
257
+ root.style.left = `${p[0]}px`;
258
+ root.style.top = `${p[1]}px`;
259
+ root.style.zIndex = `${point.coordinates[2] ?? ""}`;
260
+ switch (status) {
261
+ case 0:
262
+ htmllayer.appendChild(root);
263
+ status = 2;
264
+ break;
265
+ case 1:
266
+ status = 2;
267
+ break;
268
+ }
269
+ } else {
270
+ root.remove();
271
+ status = 0;
272
+ }
273
+
274
+ break;
275
+
276
+ case "center":
277
+ keys.add("transform");
278
+ break;
279
+ case "rotation":
280
+ keys.add("transform");
281
+ break;
282
+ default:
283
+ throw new Error(`${key} 还不支持修改`);
284
+ }
285
+ });
286
+
287
+ keys.forEach((e) => {
288
+ switch (e) {
289
+ case "transform":
290
+ root.style.transform = `translate(-${point.center[0] * 100}%,-${point.center[1] * 100}%) rotateZ(${
291
+ point.rotation
292
+ }deg)`;
293
+ root.style.transformOrigin = `${point.center[0] * 100}% ${point.center[1] * 100}%`;
294
+ break;
295
+ case "dom":
296
+ ReactDOM.render(point.element(point.props), root);
297
+ break;
298
+ }
299
+ });
300
+ };
301
+
302
+ const onMouseMove = () => {
303
+ if (delay) {
304
+ clearTimeout(delay);
305
+ delay = 0;
306
+ }
307
+ switch (status) {
308
+ case 0:
309
+ status = 1;
310
+ root.style.left = `${event.canvas[0]}px`;
311
+ root.style.top = `${event.canvas[1]}px`;
312
+ htmllayer.appendChild(root);
313
+ break;
314
+ case 1:
315
+ case 3:
316
+ root.style.left = `${event.canvas[0]}px`;
317
+ root.style.top = `${event.canvas[1]}px`;
318
+ break;
319
+ }
320
+ };
321
+
322
+ const onClick = () => {
323
+ if (status == 1) {
324
+ status = 2;
325
+ skip++;
326
+ point.coordinates = event.geography;
327
+ point.event.trigger("data-loaded");
328
+ }
329
+ };
330
+
331
+ const onPointerUp = () => {
332
+ if (delay) {
333
+ clearTimeout(delay);
334
+ delay = 0;
335
+ }
336
+ if (point.editable && status == 3) {
337
+ status = 2;
338
+ map.moveable = true;
339
+ root.style.pointerEvents = point.silent ? "none" : "all";
340
+ skip++;
341
+ point.coordinates = event.geography;
342
+ point.event.trigger("data-update");
343
+ }
344
+ };
345
+
346
+ const onDestroy = () => {
347
+ root.remove();
348
+ ReactDOM.unmountComponentAtNode(root);
349
+ event.off("view-change", onViewChange);
350
+ event.off("pointer-move", onMouseMove);
351
+ event.off("left-click", onClick);
352
+ event.off("pointer-up", onPointerUp);
353
+ point.event.off("update", onUpdate);
354
+ point.event.off("destroy", onDestroy);
355
+ };
356
+
357
+ event.on("view-change", onViewChange);
358
+ event.on("pointer-move", onMouseMove);
359
+ event.on("left-click", onClick);
360
+ event.on("pointer-up", onPointerUp);
361
+ point.event.on("update", onUpdate);
362
+ point.event.on("destroy", onDestroy);
363
+ }