-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathMapRulerRenderer.ts
More file actions
118 lines (109 loc) · 3.66 KB
/
MapRulerRenderer.ts
File metadata and controls
118 lines (109 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { EditableGeoJsonLayer } from '@nebula.gl/layers';
import { MapboxLayer } from '@deck.gl/mapbox';
import { CustomMeasureDistanceMode } from '~core/draw_tools/customDrawModes/CustomMeasureDistanceMode';
import { i18n } from '~core/localization';
import { LogicalLayerDefaultRenderer } from '~core/logical_layers/renderers/DefaultRenderer';
import { layerByOrder } from '~core/logical_layers';
import { registerMapListener } from '~core/shared_state/mapListeners';
import type {
NullableMap,
CommonHookArgs,
NotNullableMap,
} from '~core/logical_layers/types/renderer';
/* Add cyrillic alphabet to character set */
function getCyrillicCharacterSet() {
// Latin + symbols
const charSet: string[] = [];
for (let i = 32; i <= 175; i++) {
charSet.push(String.fromCharCode(i));
}
// `a`.charCodeAt() == 1040
// `я`.charCodeAt() == 1103
for (let i = 1040; i <= 1103; i++) {
charSet.push(String.fromCharCode(i));
}
return charSet;
}
export class MapRulerRenderer extends LogicalLayerDefaultRenderer {
public readonly id: string;
private _deckLayer?: MapboxLayer<unknown>;
private _removeClickListener: null | (() => void) = null;
private _removeMousemoveListener: null | (() => void) = null;
public constructor(id: string) {
super();
this.id = id;
}
willInit(args: NullableMap & CommonHookArgs): void {
// noop
}
willMount(args: NotNullableMap & CommonHookArgs) {
const map = args.map;
if (!this._deckLayer) {
// I have to use any because types expected for new MapboxLayer aren't fully correct. The config is working at the time of writing
const deckGLLayer: any = {
id: this.id,
type: EditableGeoJsonLayer,
mode: CustomMeasureDistanceMode,
parameters: {
depthTest: false, // skip z-buffer check
},
_subLayerProps: {
tooltips: {
characterSet: getCyrillicCharacterSet(),
getSize: () => 20,
},
guides: {
getFillColor: () => [0xff, 0x66, 0x00, 0xff],
getLineWidth: () => 2,
stroked: false,
pointRadiusMinPixels: 4,
pointRadiusMaxPixels: 4,
},
},
modeConfig: {
multipoint: true,
turfOptions: { units: 'kilometers' },
formatTooltip: (distance: number) => {
const km = i18n.t('km');
const m = i18n.t('m');
const distanceLabel =
distance > 1
? `${distance.toFixed(1)} ${km}.`
: `${(distance * 1000).toFixed(2)} ${m}.`;
const filler = new Array(distanceLabel.length + 2).join(' ');
return `${distanceLabel}${filler}`;
},
},
};
this._deckLayer = new MapboxLayer(deckGLLayer);
}
layerByOrder(map).addAboveLayerWithSameType(this._deckLayer, this.id);
this.addClickListener();
}
willUnMount(args: NotNullableMap & CommonHookArgs): void {
if (this._deckLayer) {
args.map.removeLayer(this._deckLayer.id);
}
this._removeClickListener?.();
this._removeMousemoveListener?.();
this._removeClickListener = null;
this._removeMousemoveListener = null;
}
public addClickListener() {
if (this._removeClickListener !== null) return;
function preventClicking(e) {
e.preventDefault();
return false;
}
function preventMousemove(e) {
return false;
}
// Use the highest priority to block map interactions from other layers
this._removeClickListener = registerMapListener('click', preventClicking, 100);
this._removeMousemoveListener = registerMapListener(
'mousemove',
preventMousemove,
100,
);
}
}