• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

antvis / L7Plot / 9478568050

12 Jun 2024 07:33AM UTC coverage: 56.968% (-2.6%) from 59.55%
9478568050

push

github

web-flow
chore: type mis (#356)

* chore: type mis

* chore: compiler options target

960 of 2222 branches covered (43.2%)

Branch coverage included in aggregate %.

2 of 2 new or added lines in 1 file covered. (100.0%)

916 existing lines in 53 files now uncovered.

2768 of 4322 relevant lines covered (64.04%)

234.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

7.89
/packages/l7plot/src/component/tooltip.ts
1
import { Scene, Marker } from '@antv/l7';
2
import EventEmitter from '@antv/event-emitter';
124✔
3
import { isString, isEqual } from '@antv/util';
124✔
4
import {
124✔
5
  Tooltip as TooltipComponent,
124✔
6
  TooltipOptions as ITooltipComponentOptions,
124✔
7
  TooltipListItem,
124✔
8
} from '@antv/l7plot-component';
124✔
9
import { get as getValueByPath } from 'lodash-es';
124✔
10
import type { IPlotLayer, ILngLat, Event, TooltipOptions, MouseEvent, TooltipItem, TooltipEvent } from '../types';
124✔
11
import { TooltipAnchorType } from '../types';
124✔
12
import { deepAssign } from '../utils';
124✔
13

14
const TRIGGER_LIST = ['mousemove', 'click'];
UNCOV
15

×
16
export class Tooltip extends EventEmitter {
17
  /**
18
   * 地图容器
UNCOV
19
   */
×
20
  protected scene: Scene;
×
21
  /**
×
22
   * 带交互的图层
×
23
   */
UNCOV
24
  protected interactionLayers: IPlotLayer[];
×
25
  /**
UNCOV
26
   * tooltip 的 schema 配置
×
27
   */
×
28
  protected options: TooltipOptions;
×
29
  /**
×
30
   * marker 实例
×
31
   */
×
32
  private marker: Marker;
33
  /**
UNCOV
34
   * tooltipComponent 实例
×
35
   */
36
  private tooltipComponent: TooltipComponent;
UNCOV
37
  /**
×
38
   * tooltip 是否可见
×
39
   */
×
40
  public currentVisible = false;
×
41
  /**
×
42
   * TooltipComponent 更新项
×
43
   */
×
44
  private lastComponentOptions: any;
45

46
  constructor(scene: Scene, interactionLayers: IPlotLayer[], options: TooltipOptions) {
UNCOV
47
    super();
×
48
    this.scene = scene;
×
49
    this.interactionLayers = interactionLayers;
×
50
    this.options = deepAssign({}, this.getDefaultOptions(), options);
×
51
    const { offsets, title, showTitle, customContent, domStyles, anchor, className } = this.options;
×
52

53
    this.marker = new Marker({
×
54
      offsets,
55
      anchor,
56
      draggable: false,
57
    });
58
    this.tooltipComponent = new TooltipComponent({
UNCOV
59
      title,
×
60
      showTitle,
×
61
      items: [],
UNCOV
62
      customContent,
×
63
      domStyles,
×
64
      className,
UNCOV
65
    });
×
66

×
67
    this.setComponent();
×
68
    this.initInteractionEvent();
×
69
  }
×
70

71
  /**
72
   * 获取默认配置
73
   */
UNCOV
74
  protected getDefaultOptions(): Partial<TooltipOptions> {
×
75
    return {
76
      showTitle: true,
77
      showComponent: true,
78
      items: [],
79
      offsets: [15, 0],
80
      trigger: 'mousemove',
81
      anchor: TooltipAnchorType['TOP-LEFT'],
UNCOV
82
    };
×
83
  }
×
84

85
  /**
86
   * 更新 tooltip 组件
87
   */
88
  public update(options: Partial<TooltipOptions>) {
UNCOV
89
    this.marker.remove();
×
90
    this.currentVisible = false;
91
    this.options = deepAssign({}, this.options, options);
92

93
    const { offsets, showTitle, customContent, domStyles, anchor, className } = this.options;
94

95
    this.marker = new Marker({
96
      offsets,
97
      anchor,
98
      draggable: false,
99
    });
100
    this.tooltipComponent.update({
101
      showTitle,
UNCOV
102
      customContent,
×
UNCOV
103
      domStyles,
×
104
      className,
×
105
    });
×
106
    this.setComponent();
×
107
  }
108

109
  private initInteractionEvent() {
110
    const trigger = this.options.trigger || 'mousemove';
UNCOV
111
    if (!TRIGGER_LIST.includes(trigger)) {
×
112
      throw new Error('trigger is mousemove or click');
113
    }
114

115
    this.interactionLayers.forEach(({ layer }) => {
116
      layer.on(trigger, this.interactionTriggerHander);
UNCOV
117
      layer.on(`un${trigger}`, this.interactionUntriggerHander);
×
118
    });
119
  }
UNCOV
120

×
UNCOV
121
  private interactionTriggerHander = (event: MouseEvent) => {
×
122
    const { feature, featureId } = event;
×
123
    const { title, customTitle, items, customItems } = this.options;
124
    // is GeoJson type
×
125
    const isGeoFeature = feature.type === 'Feature' && feature.geometry && feature.properties;
×
UNCOV
126
    // parse GeoJson properties
×
127
    const properties = isGeoFeature ? feature.properties : feature;
128
    let tooltipItems: TooltipListItem[] = [];
129

130
    if (customItems) {
×
UNCOV
131
      const items = customItems(feature);
×
UNCOV
132
      if (Array.isArray(items)) {
×
UNCOV
133
        tooltipItems = items;
×
134
      } else {
135
        throw new Error('customItems return array');
136
      }
137
    } else if (items) {
×
138
      items.forEach((item: string | TooltipItem) => {
×
139
        if (isString(item)) {
×
UNCOV
140
          const name = item.split('.').pop() || item;
×
141
          const value = getValueByPath(properties, item);
UNCOV
142
          if (value !== undefined) {
×
143
            tooltipItems.push({ name, value });
×
144
          }
×
145
        } else {
146
          const { field, alias, customValue } = item;
UNCOV
147
          const name = alias || field.split('.').pop() || field;
×
148
          const value = getValueByPath(properties, field);
×
149
          if (value !== undefined) {
×
150
            tooltipItems.push({
151
              name,
152
              value: customValue ? customValue(value, properties, featureId) : value,
153
            });
154
          }
155
        }
UNCOV
156
      });
×
UNCOV
157
    }
×
UNCOV
158

×
UNCOV
159
    const componentOptions = { title: customTitle ? customTitle(properties) : title, items: tooltipItems };
×
160

UNCOV
161
    this.updateTooltip(event, componentOptions);
×
162
  };
163

164
  private interactionUntriggerHander = () => {
165
    this.hideTooltip();
166
  };
167

×
UNCOV
168
  private unBindInteractionEvent() {
×
UNCOV
169
    const trigger = this.options.trigger || 'mousemove';
×
UNCOV
170
    this.interactionLayers.forEach(({ layer }) => {
×
171
      layer.off(trigger, this.interactionTriggerHander);
UNCOV
172
      layer.off(`un${trigger}`, this.interactionUntriggerHander);
×
173
    });
×
174
  }
×
175

176
  private updateTooltip(mouseEvent: MouseEvent, componentOptions: Partial<ITooltipComponentOptions>) {
177
    const { lngLat, x, y } = mouseEvent;
178
    if (this.options.showComponent) {
179
      this.updateComponent(componentOptions);
180
      this.setPostion(lngLat);
×
UNCOV
181
    }
×
UNCOV
182
    if (this.currentVisible) {
×
183
      const event: TooltipEvent = { type: 'tooltip:change', data: componentOptions, lngLat, x, y };
184
      this.emit('tooltip:change', event);
185
    } else {
186
      this.showTooltip();
187
      const event: TooltipEvent = { type: 'tooltip:show', data: componentOptions, lngLat, x, y };
188
      this.emit('tooltip:show', event);
UNCOV
189
    }
×
UNCOV
190
  }
×
UNCOV
191

×
UNCOV
192
  /**
×
UNCOV
193
   * tooltip 添加到地图上
×
194
   */
195
  public showTooltip() {
×
196
    if (this.currentVisible) return;
×
197
    if (this.options.showComponent) {
198
      this.scene.addMarker(this.marker);
×
199
    }
×
200
    this.currentVisible = true;
201
  }
202

203
  /**
204
   * tooltip 从地图上移除
205
   */
×
206
  public hideTooltip() {
207
    if (!this.currentVisible) return;
208
    if (this.options.showComponent) {
209
      this.marker.remove();
210
    }
211
    this.currentVisible = false;
×
UNCOV
212
    const event: Event = { type: 'tooltip:hide' };
×
UNCOV
213
    this.emit('tooltip:hide', event);
×
UNCOV
214
  }
×
215

216
  /**
217
   * 更新 tooltip 组件
124✔
218
   */
219
  private updateComponent(componentOptions: Partial<ITooltipComponentOptions>) {
220
    if (!isEqual(this.lastComponentOptions, componentOptions)) {
221
      this.tooltipComponent.update(componentOptions);
222
      this.lastComponentOptions = componentOptions;
223
    }
224
  }
225

226
  /**
227
   * 设置 tooltip 内容
228
   */
229
  private setComponent() {
230
    const tooltip = this.tooltipComponent.getContainer();
231
    const container = window.document.createElement('div');
232
    container.style.cursor = 'auto';
233
    container.style.userSelect = 'text';
234
    container.className = 'l7plot-tooltip-container';
235
    // stopPropagation
236
    ['mousemove', 'mousedown', 'mouseup', 'click', 'dblclick'].forEach((type) => {
237
      container.addEventListener(type, (e) => e.stopPropagation());
238
    });
239
    container.appendChild(tooltip);
240
    this.marker.setElement(container);
241
  }
242

243
  /**
244
   * 设置 tooltip 位置
245
   */
246
  private setPostion(position: ILngLat) {
247
    this.marker.setLnglat(position);
248
  }
249

250
  /**
251
   * 销毁
252
   */
253
  public destroy() {
254
    this.unBindInteractionEvent();
255
    this.off();
256
    this.marker.remove();
257
    this.tooltipComponent.destroy();
258
  }
259
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc