1 | import * as MapboxGl from 'mapbox-gl';
|
2 |
|
3 | export type MapEvent = (
|
4 | map: MapboxGl.Map,
|
5 |
|
6 | evt: React.SyntheticEvent<any>
|
7 | ) => void;
|
8 |
|
9 | export interface Events {
|
10 | onStyleLoad?: MapEvent;
|
11 | onResize?: MapEvent;
|
12 | onDblClick?: MapEvent;
|
13 | onClick?: MapEvent;
|
14 | onMouseMove?: MapEvent;
|
15 | onMouseOut?: MapEvent;
|
16 | onMoveStart?: MapEvent;
|
17 | onMove?: MapEvent;
|
18 | onMoveEnd?: MapEvent;
|
19 | onMouseDown?: MapEvent;
|
20 | onMouseUp?: MapEvent;
|
21 | onDragStart?: MapEvent;
|
22 | onDragEnd?: MapEvent;
|
23 | onDrag?: MapEvent;
|
24 | onZoomStart?: MapEvent;
|
25 | onZoom?: MapEvent;
|
26 | onZoomEnd?: MapEvent;
|
27 | onPitch?: MapEvent;
|
28 | onPitchStart?: MapEvent;
|
29 | onPitchEnd?: MapEvent;
|
30 | onWebGlContextLost?: MapEvent;
|
31 | onWebGlContextRestored?: MapEvent;
|
32 | onRemove?: MapEvent;
|
33 | onContextMenu?: MapEvent;
|
34 | onRender?: MapEvent;
|
35 | onError?: MapEvent;
|
36 | onSourceData?: MapEvent;
|
37 | onDataLoading?: MapEvent;
|
38 | onStyleDataLoading?: MapEvent;
|
39 | onStyleImageMissing?: MapEvent;
|
40 | onTouchCancel?: MapEvent;
|
41 | onData?: MapEvent;
|
42 | onSourceDataLoading?: MapEvent;
|
43 | onTouchMove?: MapEvent;
|
44 | onTouchEnd?: MapEvent;
|
45 | onTouchStart?: MapEvent;
|
46 | onStyleData?: MapEvent;
|
47 | onBoxZoomStart?: MapEvent;
|
48 | onBoxZoomEnd?: MapEvent;
|
49 | onBoxZoomCancel?: MapEvent;
|
50 | onRotateStart?: MapEvent;
|
51 | onRotate?: MapEvent;
|
52 | onRotateEnd?: MapEvent;
|
53 | }
|
54 |
|
55 | export type EventMapping = { [T in keyof Events]: string };
|
56 |
|
57 | export const events: EventMapping = {
|
58 | onResize: 'resize',
|
59 | onDblClick: 'dblclick',
|
60 | onClick: 'click',
|
61 | onMouseMove: 'mousemove',
|
62 | onMouseOut: 'mouseout',
|
63 | onMoveStart: 'movestart',
|
64 | onMove: 'move',
|
65 | onMoveEnd: 'moveend',
|
66 | onMouseUp: 'mouseup',
|
67 | onMouseDown: 'mousedown',
|
68 | onDragStart: 'dragstart',
|
69 | onDrag: 'drag',
|
70 | onDragEnd: 'dragend',
|
71 | onZoomStart: 'zoomstart',
|
72 | onZoom: 'zoom',
|
73 | onZoomEnd: 'zoomend',
|
74 | onPitch: 'pitch',
|
75 | onPitchStart: 'pitchstart',
|
76 | onPitchEnd: 'pitchend',
|
77 | onWebGlContextLost: 'webglcontextlost',
|
78 | onWebGlContextRestored: 'webglcontextrestored',
|
79 | onRemove: 'remove',
|
80 | onContextMenu: 'contextmenu',
|
81 | onRender: 'render',
|
82 | onError: 'error',
|
83 | onSourceData: 'sourcedata',
|
84 | onDataLoading: 'dataloading',
|
85 | onStyleDataLoading: 'styledataloading',
|
86 | onStyleImageMissing: 'styleimagemissing',
|
87 | onTouchCancel: 'touchcancel',
|
88 | onData: 'data',
|
89 | onSourceDataLoading: 'sourcedataloading',
|
90 | onTouchMove: 'touchmove',
|
91 | onTouchEnd: 'touchend',
|
92 | onTouchStart: 'touchstart',
|
93 | onStyleData: 'styledata',
|
94 | onBoxZoomStart: 'boxzoomstart',
|
95 | onBoxZoomEnd: 'boxzoomend',
|
96 | onBoxZoomCancel: 'boxzoomcancel',
|
97 | onRotateStart: 'rotatestart',
|
98 | onRotate: 'rotate',
|
99 | onRotateEnd: 'rotateend'
|
100 | };
|
101 |
|
102 | export type Listeners = {
|
103 | [T in keyof Events]: (evt: React.SyntheticEvent<any>) => void
|
104 | };
|
105 |
|
106 | export const listenEvents = (
|
107 | partialEvents: EventMapping,
|
108 | props: Partial<Events>,
|
109 | map: MapboxGl.Map
|
110 | ) =>
|
111 | Object.keys(partialEvents).reduce(
|
112 | (listeners, event) => {
|
113 | const propEvent = props[event];
|
114 |
|
115 | if (propEvent) {
|
116 |
|
117 | const listener = (evt: React.SyntheticEvent<any>) => {
|
118 | propEvent(map, evt);
|
119 | };
|
120 |
|
121 | map.on(partialEvents[event], listener);
|
122 |
|
123 | listeners[event] = listener;
|
124 | }
|
125 |
|
126 | return listeners;
|
127 | },
|
128 |
|
129 | {} as Listeners
|
130 | );
|
131 |
|
132 | export const updateEvents = (
|
133 | listeners: Listeners,
|
134 | currentProps: Partial<Events>,
|
135 | map: MapboxGl.Map
|
136 | ) => {
|
137 | const toListenOff = Object.keys(events).filter(
|
138 | eventKey =>
|
139 | listeners[eventKey] && typeof currentProps[eventKey] !== 'function'
|
140 | );
|
141 |
|
142 | toListenOff.forEach(key => {
|
143 | map.off(events[key], listeners[key]);
|
144 | delete listeners[key];
|
145 | });
|
146 |
|
147 | const toListenOn = Object.keys(events)
|
148 | .filter(key => !listeners[key] && typeof currentProps[key] === 'function')
|
149 | .reduce((acc, next) => ((acc[next] = events[next]), acc), {});
|
150 |
|
151 | const newListeners = listenEvents(toListenOn, currentProps, map);
|
152 |
|
153 | return { ...listeners, ...newListeners };
|
154 | };
|