# Context Menu
ContextMenu is a context menu that displays a right-click menu interface.
# Common Methods
| Method | Description |
|---|---|
| add | Add menu item |
| show | Show menu |
| hide | Hide menu |
| toggle | Toggle menu visibility |
# Menu Item Types
| Type | Description |
|---|---|
| seperator | Separator line |
| custom | Custom menu item |
| multi | Multiple buttons |
| submenu | Submenu item |
| hovermenu | Hover menu item |
| normal | Default normal menu item |
# Examples
# Map Context Menu
Map context menu (opens new window)
// Selected icon, or specify src path directly
const checkIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAANpJREFUOE9jZKAQMFKon2FgDKjZHVHf4rqiEeR6kl1QuzOyn+E/4/lmj2WLSDagekdkASMjg1aL+/I0WNgR7YLaHRG2/xgZYlrdV6QjBzzRBtTsijzzl4nVvd1l0VucBtTsjlz5/z/jt1a3ZYnIimp2RZ7//+9fQ6vHyo3o0Q53Qc32CAcGpv88DIxMxQyMDB9aXJcHghTX7IxcyMjAeLTZfdksbGkGqxdqdkUuZ2BgkPjPyDCFgeG/W6srqr+JCoPqXZG9jAwM9iyszy0aHA/8wZViiQ7EYWwAAPShQBF/1IlVAAAAAElFTkSuQmCC";
map.setMenu(event => {
return new vjmap.ContextMenu({
event: event.originalEvent,
theme: "dark", //light
width: "250px",
items: [
{type: 'custom', markup: `<span style="color: #ffff00; padding-left: 30px">Context menu demo</span>`},
{type: 'multi', items: [
{label: 'Fit to map', onClick: () => { map.fitMapBounds(); }},
{label: 'Reset rotation', onClick: () => { map.setBearing(0); }},
{label: 'Reset pitch', onClick: () => { map.setPitch(0); }},
]},
{label: 'Get coordinates at this position', onClick: () => {
let point = map.fromLngLat(event.lngLat);
map.logInfo(`Current coordinates: x: ${point.x}, y: ${point.y}`);
}},
{type: 'seperator'},
{type: 'submenu', label: 'Map zoom', items: [
{label: 'Zoom in one level', onClick: () => { map.setZoom(map.getZoom() + 1)}},
{label: 'Zoom out one level', onClick: () => { map.setZoom(map.getZoom() - 1)}, enabled: map.getZoom() - 1 > 0},
{label: 'Zoom to minimum level', onClick: () => { map.setZoom(0)}},
{label: 'Fly to this position', onClick: () => {
map.flyTo({
center: event.lngLat,
pitch: 60,
zoom: 5
})
}}
]},
{type: 'hovermenu', label: 'Map settings', items: [
{
label: 'Double-click to zoom',
icon: map.doubleClickZoom.isEnabled() ? checkIcon : "",
onClick: () => {
if (map.doubleClickZoom.isEnabled()) {
map.doubleClickZoom.disable()
} else {
map.doubleClickZoom.enable()
}
}
},
{
label: 'Allow map rotation',
icon: map.dragRotate.isEnabled() ? checkIcon : "",
onClick: () => {
if (map.dragRotate.isEnabled()) {
map.dragRotate.disable();
} else {
map.dragRotate.enable();
}
}
},
{
label: 'Allow map pitch',
icon: map.getMaxPitch() != 0 ? checkIcon : "",
onClick: () => {
if (map.getMaxPitch() == 0) {
map.setMaxPitch(85)
} else {
map.setMaxPitch(0)
}
}
}
]}
]
});
})
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
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
# Overlay Layer Context Menu
Overlay layer context menu (opens new window)
// Show menu when clicking an overlay. The key can be customized. If the function returns null, the map context menu above is triggered. If the function returns non-null, this menu is shown
map.setMenu(event => {
let features = map.queryRenderedFeatures(event.point, {
layers: [polygon.layerId]
});
if (features.length == 0) {
// If the click position has no features from the polygon layer above, return null to trigger the default map menu
return null;
}
// If the click position has features from the polygon layer, show this layer's custom context menu
return new vjmap.ContextMenu({
event: event.originalEvent,
theme: "dark", //light
width: "250px",
items: [
{type: 'custom', markup: `<span style="color: #ffff00; padding-left: 30px">I am the polygon layer context menu</span>`},
{
label: 'View selected polygon info',
onClick: () => {
map.logInfo(`Current polygon ID: ${features[0].properties.id}, Current polygon color: ${features[0].properties.color}`);
}
},
{
label: 'Delete',
onClick: () => {
let data = polygon.getData();
data.features = data.features.filter(f => f.id != features[0].properties.id);
polygon.setData(data);
}
}
]
});
}, "overlay")
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
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
# Marker Context Menu
Marker context menu (opens new window)
// Unlike polygon and other overlay layers, marker is a div while overlay layers are canvas-rendered and share the same div as the map
// So marker right-click must be triggered by its own div's context menu
marker.getElement().addEventListener("mousedown", event => {
if (event.button != 2) return;// Not right-click
// Prevent default map context menu
event.preventDefault();
event.stopPropagation();
return new vjmap.ContextMenu({
event: event,
theme: "dark", //light
width: "250px",
items: [
{type: 'custom', markup: `<span style="color: #ffff00; padding-left: 30px">I am the Marker context menu</span>`},
{
label: 'Get this Marker info',
onClick: () => {
map.logInfo(`Current Marker ID: ${marker.id}`);
}
}
]
});
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Type Definitions
/**
* Context menu.
*
**/
export class ContextMenu {
private options;
private menuControl;
private position;
/**
* Creates a new ContextMenu menu
* @param {object} opts options which build the menu e.g. position and items
* @param {number} opts.width sets the width of the menu including children
* @param {object} opts.event Event object
* @param {theme} opts.theme Custom theme, supports dark and light, default dark
* @param {boolean} opts.isSticky sets how the menu appears, follow the mouse or sticky
* @param {Array<ContextMenuItem>} opts.items sets the default items in the menu
*/
constructor(opts: ContextMenuOptions);
/**
* Adds item to this ContextMenu menu instance
* @param {ContextMenuItem} item item to add to the ContextMenu menu
*/
add(item: any): void;
/**
* Makes this ContextMenu menu visible
*/
show(): void;
/**
* Hides this ContextMenu menu
*/
hide(): void;
/**
* Toggle visibility of menu
*/
toggle(): void;
}
/**
* Context menu options.
*
**/
export interface ContextMenuOptions {
/** Event object. */
event: Event;
/** Menu width (including submenus), pixels, default 150px. */
width?: string;
/** Menu theme. (dark and light, default dark)*/
theme?: string;
/** Inner width of the menu outer container, used to auto-adjust position when menu exceeds bounds; default is window width. Can be set via map.getContainer().getBoundingClientRect().width */
innerWidth?: number;
/** Inner height of the menu outer container, used to auto-adjust position when menu exceeds bounds; default is window height. Can be set via map.getContainer().getBoundingClientRect().height */
innerHeight?: number;
/** Menu items */
items: ContextMenuSubItemOptions[];
}
/**
* Context menu sub-item options.
*
**/
export interface ContextMenuSubItemOptions {
/** Submenu type. */
type?: "custom" | "multi" | "Button" | "seperator" | "submenu" | "hovermenu" | "normal";
/** Custom HTML content when type is 'custom' */
markup?: string;
/** Submenu items when type is 'multi'*/
items?: ContextMenuSubItemOptions[];
/** Click handler*/
onClick?: Function;
/** Menu label*/
label?: string;
/** Shortcut key*/
shortcut?: string;
/** Whether enabled*/
enabled?: boolean;
/** CSS icon*/
cssIcon?: string;
/** Icon*/
icon?: string;
}
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
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
← Popup div Overlay →