my-openlayer 0.1.18 → 1.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.
@@ -5,15 +5,31 @@ import VectorSource from "ol/source/Vector";
5
5
  import BaseLayer from "ol/layer/Base";
6
6
  import ImageLayer from "ol/layer/Image";
7
7
  import ImageSource from "ol/source/Image";
8
+ import { EventManager, MapEventData } from "./EventManager";
9
+ /**
10
+ * 地图工具类
11
+ * 提供地图的基础操作功能
12
+ */
8
13
  export default class MapTools {
9
14
  private readonly map;
15
+ private eventManager;
16
+ private errorHandler;
10
17
  constructor(map: Map);
11
18
  /**
12
19
  * 根据名称获取图层
13
20
  * @param layerName 图层名称
21
+ * @returns 图层数组
22
+ * @throws 当参数无效时抛出错误
14
23
  */
15
- getLayerByLayerName(layerName: string | string[]): (BaseLayer | VectorLayer<VectorSource<import("ol/geom").Geometry>> | ImageLayer<ImageSource>)[];
16
- static getLayerByLayerName(map: Map, layerName: string | string[]): (BaseLayer | VectorLayer<VectorSource<import("ol/geom").Geometry>> | ImageLayer<ImageSource>)[];
24
+ getLayerByLayerName(layerName: string | string[]): (VectorLayer<VectorSource> | BaseLayer | ImageLayer<ImageSource>)[];
25
+ /**
26
+ * 根据图层名称获取图层
27
+ * @param map 地图实例
28
+ * @param layerName 图层名称
29
+ * @returns 图层数组
30
+ * @throws 当参数无效时抛出错误
31
+ */
32
+ static getLayerByLayerName(map: Map, layerName: string | string[]): (VectorLayer<VectorSource> | BaseLayer | ImageLayer<ImageSource>)[];
17
33
  /**
18
34
  * 设置地图裁剪
19
35
  */
@@ -21,29 +37,83 @@ export default class MapTools {
21
37
  /**
22
38
  * 移除图层
23
39
  * @param layerName 图层名称
40
+ * @throws 当参数无效时抛出错误
24
41
  */
25
42
  removeLayer(layerName: string | string[]): void;
26
43
  /**
27
- * 移除图层
44
+ * 移除图层(静态方法,兼容性保留)
28
45
  * @param map 地图对象
29
46
  * @param layerName 图层名称
47
+ * @throws 当参数无效时抛出错误
30
48
  */
31
49
  static removeLayer(map: Map, layerName: string | string[]): void;
50
+ /**
51
+ * 设置图层可见性
52
+ * @param layerName 图层名称
53
+ * @param visible 是否可见
54
+ * @throws 当参数无效时抛出错误
55
+ */
32
56
  setLayerVisible(layerName: string, visible: boolean): void;
33
57
  /**
34
58
  * 设置图层可见性
35
- * @param map
59
+ * @param map 地图实例
36
60
  * @param layerName 图层名称
37
61
  * @param visible 是否可见
62
+ * @throws 当参数无效时抛出错误
38
63
  */
39
64
  static setLayerVisible: (map: Map, layerName: string, visible: boolean) => void;
40
- mapOnEvent(eventType: EventType, callback: (feature?: any, e?: any) => void, clickType?: 'point' | 'line' | 'polygon' | undefined): void;
41
65
  /**
42
66
  * 地图监听事件
43
- * @param map
44
67
  * @param eventType 事件类型
45
- * @param clickType 点击类型
46
68
  * @param callback 回调函数
69
+ * @param options 事件选项
70
+ * @returns 事件监听器ID
71
+ * @throws 当参数无效时抛出错误
72
+ */
73
+ mapOnEvent(eventType: EventType, callback: (feature?: any, e?: any) => void, options?: {
74
+ clickType?: 'point' | 'line' | 'polygon';
75
+ once?: boolean;
76
+ filter?: (event: MapEventData) => boolean;
77
+ }): string;
78
+ /**
79
+ * 地图监听事件(静态方法,兼容性保留)
80
+ * @param map 地图实例
81
+ * @param eventType 事件类型
82
+ * @param callback 回调函数
83
+ * @param clickType 点击类型
84
+ * @throws 当参数无效时抛出错误
85
+ * @deprecated 推荐使用实例方法 mapOnEvent
47
86
  */
48
87
  static mapOnEvent(map: Map, eventType: EventType, callback: (feature?: any, e?: any) => void, clickType?: 'point' | 'line' | 'polygon'): void;
88
+ /**
89
+ * 兼容性方法:使用传统方式注册事件
90
+ * @private
91
+ */
92
+ private registerEventWithManager;
93
+ /**
94
+ * 转换事件类型
95
+ * @private
96
+ */
97
+ private convertToMapEventType;
98
+ /**
99
+ * 移除事件监听器
100
+ * @param listenerId 监听器ID
101
+ * @returns 是否成功移除
102
+ */
103
+ removeEventListener(listenerId: string): boolean;
104
+ /**
105
+ * 移除指定类型的所有事件监听器
106
+ * @param eventType 事件类型
107
+ */
108
+ removeAllEventListeners(eventType?: EventType): void;
109
+ /**
110
+ * 获取 EventManager 实例
111
+ * @returns EventManager 实例
112
+ */
113
+ getEventManager(): EventManager;
114
+ /**
115
+ * 获取地图实例
116
+ * @returns 地图实例
117
+ */
118
+ getMap(): Map;
49
119
  }
@@ -4,35 +4,72 @@ import VectorSource from "ol/source/Vector";
4
4
  import GeoJSON from "ol/format/GeoJSON";
5
5
  import { Fill, Style } from "ol/style";
6
6
  import { getVectorContext } from "ol/render";
7
+ import { EventManager } from "./EventManager";
8
+ import { ErrorHandler, ErrorType } from "../utils/ErrorHandler";
9
+ /**
10
+ * 地图工具类
11
+ * 提供地图的基础操作功能
12
+ */
7
13
  class MapTools {
8
14
  constructor(map) {
9
- this.map = map;
15
+ this.errorHandler = ErrorHandler.getInstance();
16
+ try {
17
+ ErrorHandler.validateMap(map);
18
+ this.map = map;
19
+ this.eventManager = new EventManager(map);
20
+ }
21
+ catch (error) {
22
+ this.errorHandler.createAndHandleError(`Failed to initialize MapTools: ${error}`, ErrorType.MAP_ERROR, { map, error });
23
+ throw error;
24
+ }
10
25
  }
11
26
  /**
12
27
  * 根据名称获取图层
13
28
  * @param layerName 图层名称
29
+ * @returns 图层数组
30
+ * @throws 当参数无效时抛出错误
14
31
  */
15
32
  getLayerByLayerName(layerName) {
16
- if (!this.map)
17
- return [];
33
+ if (!this.map) {
34
+ throw new Error('Map instance is not available');
35
+ }
18
36
  return MapTools.getLayerByLayerName(this.map, layerName);
19
37
  }
38
+ /**
39
+ * 根据图层名称获取图层
40
+ * @param map 地图实例
41
+ * @param layerName 图层名称
42
+ * @returns 图层数组
43
+ * @throws 当参数无效时抛出错误
44
+ */
20
45
  static getLayerByLayerName(map, layerName) {
46
+ if (!map) {
47
+ throw new Error('Map instance is required');
48
+ }
49
+ if (!layerName || (typeof layerName !== 'string' && !Array.isArray(layerName))) {
50
+ throw new Error('Valid layer name is required');
51
+ }
21
52
  const targetLayer = [];
22
- const layers = map.getLayers().getArray();
23
- Object.values(layers).forEach((layer) => {
24
- const _layerName = layer.get('layerName');
25
- if (typeof layerName === "string") {
26
- if (_layerName && _layerName === layerName) {
27
- targetLayer.push(layer);
53
+ try {
54
+ const layers = map.getLayers().getArray();
55
+ layers.forEach((layer) => {
56
+ const _layerName = layer.get('layerName');
57
+ if (typeof layerName === "string") {
58
+ if (_layerName && _layerName === layerName) {
59
+ targetLayer.push(layer);
60
+ }
28
61
  }
29
- }
30
- else {
31
- if (_layerName && layerName.includes(_layerName)) {
32
- targetLayer.push(layer);
62
+ else {
63
+ if (_layerName && layerName.includes(_layerName)) {
64
+ targetLayer.push(layer);
65
+ }
33
66
  }
34
- }
35
- });
67
+ });
68
+ }
69
+ catch (error) {
70
+ console.error('Error getting layers:', error);
71
+ throw new Error('Failed to retrieve layers from map');
72
+ }
36
73
  return targetLayer;
37
74
  }
38
75
  /**
@@ -72,84 +109,249 @@ class MapTools {
72
109
  /**
73
110
  * 移除图层
74
111
  * @param layerName 图层名称
112
+ * @throws 当参数无效时抛出错误
75
113
  */
76
114
  removeLayer(layerName) {
77
- if (!this.map)
78
- return;
79
- MapTools.removeLayer(this.map, layerName);
115
+ if (!this.map) {
116
+ throw new Error('Map instance is not available');
117
+ }
118
+ try {
119
+ const layers = this.getLayerByLayerName(layerName);
120
+ layers.forEach(layer => {
121
+ this.map.removeLayer(layer);
122
+ });
123
+ }
124
+ catch (error) {
125
+ console.error('Error removing layers:', error);
126
+ throw new Error('Failed to remove layers from map');
127
+ }
80
128
  }
81
129
  /**
82
- * 移除图层
130
+ * 移除图层(静态方法,兼容性保留)
83
131
  * @param map 地图对象
84
132
  * @param layerName 图层名称
133
+ * @throws 当参数无效时抛出错误
85
134
  */
86
135
  static removeLayer(map, layerName) {
87
- const layers = MapTools.getLayerByLayerName(map, layerName);
88
- layers.forEach(layer => {
89
- map.removeLayer(layer);
90
- });
136
+ if (!map) {
137
+ throw new Error('Map instance is required');
138
+ }
139
+ try {
140
+ const layers = MapTools.getLayerByLayerName(map, layerName);
141
+ layers.forEach(layer => {
142
+ map.removeLayer(layer);
143
+ });
144
+ }
145
+ catch (error) {
146
+ console.error('Error removing layers:', error);
147
+ throw new Error('Failed to remove layers from map');
148
+ }
91
149
  }
150
+ /**
151
+ * 设置图层可见性
152
+ * @param layerName 图层名称
153
+ * @param visible 是否可见
154
+ * @throws 当参数无效时抛出错误
155
+ */
92
156
  setLayerVisible(layerName, visible) {
93
- if (!this.map)
94
- return;
95
- MapTools.setLayerVisible(this.map, layerName, visible);
96
- }
97
- mapOnEvent(eventType, callback, clickType) {
98
- if (!this.map)
99
- return;
100
- MapTools.mapOnEvent(this.map, eventType, callback, clickType);
157
+ if (!this.map) {
158
+ throw new Error('Map instance is not available');
159
+ }
160
+ try {
161
+ const layers = this.getLayerByLayerName(layerName);
162
+ layers.forEach(layer => {
163
+ layer.setVisible(visible);
164
+ });
165
+ }
166
+ catch (error) {
167
+ console.error('Error setting layer visibility:', error);
168
+ throw new Error('Failed to set layer visibility');
169
+ }
101
170
  }
102
171
  /**
103
172
  * 地图监听事件
104
- * @param map
105
173
  * @param eventType 事件类型
106
- * @param clickType 点击类型
107
174
  * @param callback 回调函数
175
+ * @param options 事件选项
176
+ * @returns 事件监听器ID
177
+ * @throws 当参数无效时抛出错误
178
+ */
179
+ mapOnEvent(eventType, callback, options) {
180
+ try {
181
+ ErrorHandler.validateMap(this.map);
182
+ if (!eventType) {
183
+ throw new Error('Event type is required');
184
+ }
185
+ if (typeof callback !== 'function') {
186
+ throw new Error('Callback must be a function');
187
+ }
188
+ return this.registerEventWithManager(eventType, callback, options);
189
+ }
190
+ catch (error) {
191
+ this.errorHandler.createAndHandleError(`Failed to register map event: ${error}`, ErrorType.COMPONENT_ERROR, { eventType, callback, options, error });
192
+ throw error;
193
+ }
194
+ }
195
+ /**
196
+ * 地图监听事件(静态方法,兼容性保留)
197
+ * @param map 地图实例
198
+ * @param eventType 事件类型
199
+ * @param callback 回调函数
200
+ * @param clickType 点击类型
201
+ * @throws 当参数无效时抛出错误
202
+ * @deprecated 推荐使用实例方法 mapOnEvent
108
203
  */
109
204
  static mapOnEvent(map, eventType, callback, clickType) {
110
- const clickTypeObj = {
111
- point: ['point'],
112
- line: ['line'],
113
- polygon: ['polygon', 'MultiPolygon']
114
- };
115
- if (eventType === "click") {
116
- map.on("click", (e) => {
117
- // 获取点位 feature
118
- const pixel = map.getEventPixel(e.originalEvent);
119
- const features = map.getFeaturesAtPixel(pixel);
120
- let feature = undefined;
121
- if (features.length > 0)
122
- feature = features[0];
123
- callback(feature, { features, pixel });
124
- });
205
+ const errorHandler = ErrorHandler.getInstance();
206
+ try {
207
+ ErrorHandler.validateMap(map);
208
+ if (!eventType) {
209
+ throw new Error('Event type is required');
210
+ }
211
+ if (typeof callback !== 'function') {
212
+ throw new Error('Callback must be a function');
213
+ }
214
+ const eventManager = new EventManager(map);
215
+ const mapTools = new MapTools(map);
216
+ mapTools.registerEventWithManager(eventType, callback, { clickType });
217
+ }
218
+ catch (error) {
219
+ errorHandler.createAndHandleError(`Failed to register static map event: ${error}`, ErrorType.COMPONENT_ERROR, { map, eventType, callback, clickType, error });
220
+ throw error;
125
221
  }
126
- else if (eventType === 'moveend') {
127
- map.on('moveend', function () {
128
- const zoom = map.getView().getZoom();
129
- if (zoom) {
130
- callback(zoom);
222
+ }
223
+ /**
224
+ * 兼容性方法:使用传统方式注册事件
225
+ * @private
226
+ */
227
+ registerEventWithManager(eventType, callback, options) {
228
+ const mapEventType = this.convertToMapEventType(eventType);
229
+ const eventCallback = (event) => {
230
+ try {
231
+ if (eventType === 'click') {
232
+ const feature = event.feature;
233
+ const extraData = {
234
+ features: event.features || [],
235
+ pixel: event.pixel
236
+ };
237
+ // 应用点击类型过滤
238
+ if (options?.clickType && feature) {
239
+ const geometryType = feature.getGeometry()?.getType();
240
+ const clickTypeMap = {
241
+ point: ['Point', 'MultiPoint'],
242
+ line: ['LineString', 'MultiLineString'],
243
+ polygon: ['Polygon', 'MultiPolygon']
244
+ };
245
+ if (geometryType && !clickTypeMap[options.clickType].includes(geometryType)) {
246
+ return; // 不符合点击类型过滤条件
247
+ }
248
+ }
249
+ callback(feature, extraData);
131
250
  }
132
- });
251
+ else if (eventType === 'moveend') {
252
+ callback(event.zoom);
253
+ }
254
+ else if (eventType === 'hover') {
255
+ callback({
256
+ features: event.features || [],
257
+ pixel: event.pixel
258
+ });
259
+ }
260
+ }
261
+ catch (error) {
262
+ this.errorHandler.createAndHandleError(`Error in event callback: ${error}`, ErrorType.COMPONENT_ERROR, { eventType, event, error });
263
+ }
264
+ };
265
+ return this.eventManager.on(mapEventType, eventCallback, {
266
+ once: options?.once,
267
+ filter: options?.filter
268
+ });
269
+ }
270
+ /**
271
+ * 转换事件类型
272
+ * @private
273
+ */
274
+ convertToMapEventType(eventType) {
275
+ const typeMap = {
276
+ 'click': 'click',
277
+ 'hover': 'hover',
278
+ 'moveend': 'moveend'
279
+ };
280
+ return typeMap[eventType] || 'click';
281
+ }
282
+ /**
283
+ * 移除事件监听器
284
+ * @param listenerId 监听器ID
285
+ * @returns 是否成功移除
286
+ */
287
+ removeEventListener(listenerId) {
288
+ try {
289
+ return this.eventManager.off(listenerId);
133
290
  }
134
- else if (eventType === 'hover') {
135
- map.on('pointermove', (e) => {
136
- const pixel = map.getEventPixel(e.originalEvent);
137
- const features = map.getFeaturesAtPixel(pixel);
138
- callback({ features, pixel });
139
- });
291
+ catch (error) {
292
+ this.errorHandler.createAndHandleError(`Failed to remove event listener: ${error}`, ErrorType.COMPONENT_ERROR, { listenerId, error });
293
+ return false;
140
294
  }
141
295
  }
296
+ /**
297
+ * 移除指定类型的所有事件监听器
298
+ * @param eventType 事件类型
299
+ */
300
+ removeAllEventListeners(eventType) {
301
+ try {
302
+ if (eventType) {
303
+ const mapEventType = this.convertToMapEventType(eventType);
304
+ this.eventManager.offAll(mapEventType);
305
+ }
306
+ else {
307
+ this.eventManager.clear();
308
+ }
309
+ }
310
+ catch (error) {
311
+ this.errorHandler.createAndHandleError(`Failed to remove event listeners: ${error}`, ErrorType.COMPONENT_ERROR, { eventType, error });
312
+ }
313
+ }
314
+ /**
315
+ * 获取 EventManager 实例
316
+ * @returns EventManager 实例
317
+ */
318
+ getEventManager() {
319
+ return this.eventManager;
320
+ }
321
+ /**
322
+ * 获取地图实例
323
+ * @returns 地图实例
324
+ */
325
+ getMap() {
326
+ return this.map;
327
+ }
142
328
  }
143
329
  /**
144
330
  * 设置图层可见性
145
- * @param map
331
+ * @param map 地图实例
146
332
  * @param layerName 图层名称
147
333
  * @param visible 是否可见
334
+ * @throws 当参数无效时抛出错误
148
335
  */
149
336
  MapTools.setLayerVisible = (map, layerName, visible) => {
150
- const layers = MapTools.getLayerByLayerName(map, layerName);
151
- layers.forEach(layer => {
152
- layer.setVisible(visible);
153
- });
337
+ if (!map) {
338
+ throw new Error('Map instance is required');
339
+ }
340
+ if (typeof layerName !== 'string') {
341
+ throw new Error('Layer name must be a string');
342
+ }
343
+ if (typeof visible !== 'boolean') {
344
+ throw new Error('Visible parameter must be a boolean');
345
+ }
346
+ try {
347
+ const layers = MapTools.getLayerByLayerName(map, layerName);
348
+ layers.forEach(layer => {
349
+ layer.setVisible(visible);
350
+ });
351
+ }
352
+ catch (error) {
353
+ console.error('Error setting layer visibility:', error);
354
+ throw new Error('Failed to set layer visibility');
355
+ }
154
356
  };
155
357
  export default MapTools;
@@ -1,7 +1,8 @@
1
1
  import Map from "ol/Map";
2
2
  import { MeasureHandlerType } from "../types";
3
3
  /**
4
- * @classdesc MeausreHandler
4
+ * 测量工具处理类
5
+ * 提供距离和面积测量功能
5
6
  */
6
7
  export default class MeasureHandler {
7
8
  private readonly source;
@@ -9,14 +10,19 @@ export default class MeasureHandler {
9
10
  private sketch;
10
11
  private helpTooltipElement;
11
12
  private helpTooltip;
12
- private _map;
13
+ private readonly _map;
13
14
  private measureTooltipElement;
14
15
  private measureTooltip;
15
- private continuePolygonMsg;
16
- private continueLineMsg;
16
+ private readonly continuePolygonMsg;
17
+ private readonly continueLineMsg;
17
18
  private _tipsCollection;
18
19
  private _mouseListener;
19
20
  private _draw;
21
+ /**
22
+ * 构造函数
23
+ * @param map OpenLayers地图实例
24
+ * @throws 当地图实例无效时抛出错误
25
+ */
20
26
  constructor(map: Map);
21
27
  /**
22
28
  * destory the object
@@ -35,8 +41,9 @@ export default class MeasureHandler {
35
41
  */
36
42
  formatArea(polygon: any): string;
37
43
  /**
38
- *
39
- * @param {String} type the values such as 'Polygon','LineString'
44
+ * 开始测量
45
+ * @param type 测量类型
46
+ * @throws 当测量类型无效时抛出错误
40
47
  */
41
48
  start(type: MeasureHandlerType): void;
42
49
  /**
@@ -7,12 +7,21 @@ import { Vector as VectorLayer } from 'ol/layer.js';
7
7
  import { getArea, getLength } from 'ol/sphere.js';
8
8
  import { unByKey } from 'ol/Observable.js';
9
9
  /**
10
- * @classdesc MeausreHandler
10
+ * 测量工具处理类
11
+ * 提供距离和面积测量功能
11
12
  */
12
13
  export default class MeasureHandler {
14
+ /**
15
+ * 构造函数
16
+ * @param map OpenLayers地图实例
17
+ * @throws 当地图实例无效时抛出错误
18
+ */
13
19
  constructor(map) {
14
- this._map = null;
15
20
  this._draw = null;
21
+ if (!map) {
22
+ throw new Error('Map instance is required');
23
+ }
24
+ this._map = map;
16
25
  this.source = new VectorSource();
17
26
  this.vector = new VectorLayer({
18
27
  source: this.source,
@@ -37,7 +46,6 @@ export default class MeasureHandler {
37
46
  }),
38
47
  zIndex: 999,
39
48
  });
40
- this._map = map;
41
49
  /**
42
50
  * Currently drawn feature.
43
51
  * @type {import("ol/Feature.js").default}
@@ -149,17 +157,27 @@ export default class MeasureHandler {
149
157
  return output;
150
158
  }
151
159
  /**
152
- *
153
- * @param {String} type the values such as 'Polygon','LineString'
160
+ * 开始测量
161
+ * @param type 测量类型
162
+ * @throws 当测量类型无效时抛出错误
154
163
  */
155
164
  start(type) {
165
+ if (!type || (type !== 'LineString' && type !== 'Polygon')) {
166
+ throw new Error('Invalid measure type. Must be "LineString" or "Polygon"');
167
+ }
156
168
  if (!this._map) {
157
169
  throw new Error("MeasureHandler has not been register to the map");
158
170
  }
159
- this.createMeasureTooltip();
160
- this.createHelpTooltip();
161
- if (this._draw) {
162
- this._map.removeInteraction(this._draw);
171
+ try {
172
+ this.createMeasureTooltip();
173
+ this.createHelpTooltip();
174
+ if (this._draw) {
175
+ this._map.removeInteraction(this._draw);
176
+ }
177
+ }
178
+ catch (error) {
179
+ console.error('Error starting measurement:', error);
180
+ throw new Error('Failed to start measurement');
163
181
  }
164
182
  this._draw = new Draw({
165
183
  source: this.source,
@@ -196,22 +214,25 @@ export default class MeasureHandler {
196
214
  this.sketch = evt.feature;
197
215
  /** @type {import("ol/coordinate.js").Coordinate|undefined} */
198
216
  let tooltipCoord = evt?.coordinate;
199
- listener = this.sketch.getGeometry().on('change', (evt) => {
200
- const geom = evt.target;
201
- let output;
202
- if (geom instanceof Polygon) {
203
- output = this.formatArea(geom);
204
- tooltipCoord = geom.getInteriorPoint().getCoordinates();
205
- }
206
- else if (geom instanceof LineString) {
207
- output = this.formatLength(geom);
208
- tooltipCoord = geom.getLastCoordinate();
209
- }
210
- if (this.measureTooltipElement) {
211
- this.measureTooltipElement.innerHTML = output;
212
- }
213
- this.measureTooltip?.setPosition(tooltipCoord);
214
- });
217
+ const geometry = this.sketch?.getGeometry();
218
+ if (geometry) {
219
+ listener = geometry.on('change', (evt) => {
220
+ const geom = evt.target;
221
+ let output;
222
+ if (geom instanceof Polygon) {
223
+ output = this.formatArea(geom);
224
+ tooltipCoord = geom.getInteriorPoint().getCoordinates();
225
+ }
226
+ else if (geom instanceof LineString) {
227
+ output = this.formatLength(geom);
228
+ tooltipCoord = geom.getLastCoordinate();
229
+ }
230
+ if (this.measureTooltipElement) {
231
+ this.measureTooltipElement.innerHTML = output;
232
+ }
233
+ this.measureTooltip?.setPosition(tooltipCoord);
234
+ });
235
+ }
215
236
  });
216
237
  this._draw.on('drawend', () => {
217
238
  if (this.measureTooltipElement) {