@mapbox/mapbox-gl-draw
Version:
A drawing component for Mapbox GL JS
192 lines (156 loc) • 5.42 kB
JavaScript
import * as Constants from './constants.js';
const classTypes = ['mode', 'feature', 'mouse'];
export default function(ctx) {
const buttonElements = {};
let activeButton = null;
let currentMapClasses = {
mode: null, // e.g. mode-direct_select
feature: null, // e.g. feature-vertex
mouse: null // e.g. mouse-move
};
let nextMapClasses = {
mode: null,
feature: null,
mouse: null
};
function clearMapClasses() {
queueMapClasses({mode:null, feature:null, mouse:null});
updateMapClasses();
}
function queueMapClasses(options) {
nextMapClasses = Object.assign(nextMapClasses, options);
}
function updateMapClasses() {
if (!ctx.container) return;
const classesToRemove = [];
const classesToAdd = [];
classTypes.forEach((type) => {
if (nextMapClasses[type] === currentMapClasses[type]) return;
classesToRemove.push(`${type}-${currentMapClasses[type]}`);
if (nextMapClasses[type] !== null) {
classesToAdd.push(`${type}-${nextMapClasses[type]}`);
}
});
if (classesToRemove.length > 0) {
ctx.container.classList.remove(...classesToRemove);
}
if (classesToAdd.length > 0) {
ctx.container.classList.add(...classesToAdd);
}
currentMapClasses = Object.assign(currentMapClasses, nextMapClasses);
}
function createControlButton(id, options = {}) {
const button = document.createElement('button');
button.className = `${Constants.classes.CONTROL_BUTTON} ${options.className}`;
button.setAttribute('title', options.title);
options.container.appendChild(button);
button.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
const clickedButton = e.target;
if (clickedButton === activeButton) {
deactivateButtons();
options.onDeactivate();
return;
}
setActiveButton(id);
options.onActivate();
}, true);
return button;
}
function deactivateButtons() {
if (!activeButton) return;
activeButton.classList.remove(Constants.classes.ACTIVE_BUTTON);
activeButton = null;
}
function setActiveButton(id) {
deactivateButtons();
const button = buttonElements[id];
if (!button) return;
if (button && id !== 'trash') {
button.classList.add(Constants.classes.ACTIVE_BUTTON);
activeButton = button;
}
}
function addButtons() {
const controls = ctx.options.controls;
const controlGroup = document.createElement('div');
controlGroup.className = `${Constants.classes.CONTROL_GROUP} ${Constants.classes.CONTROL_BASE}`;
if (!controls) return controlGroup;
if (controls[Constants.types.LINE]) {
buttonElements[Constants.types.LINE] = createControlButton(Constants.types.LINE, {
container: controlGroup,
className: Constants.classes.CONTROL_BUTTON_LINE,
title: `LineString tool ${ctx.options.keybindings ? '(l)' : ''}`,
onActivate: () => ctx.events.changeMode(Constants.modes.DRAW_LINE_STRING),
onDeactivate: () => ctx.events.trash()
});
}
if (controls[Constants.types.POLYGON]) {
buttonElements[Constants.types.POLYGON] = createControlButton(Constants.types.POLYGON, {
container: controlGroup,
className: Constants.classes.CONTROL_BUTTON_POLYGON,
title: `Polygon tool ${ctx.options.keybindings ? '(p)' : ''}`,
onActivate: () => ctx.events.changeMode(Constants.modes.DRAW_POLYGON),
onDeactivate: () => ctx.events.trash()
});
}
if (controls[Constants.types.POINT]) {
buttonElements[Constants.types.POINT] = createControlButton(Constants.types.POINT, {
container: controlGroup,
className: Constants.classes.CONTROL_BUTTON_POINT,
title: `Marker tool ${ctx.options.keybindings ? '(m)' : ''}`,
onActivate: () => ctx.events.changeMode(Constants.modes.DRAW_POINT),
onDeactivate: () => ctx.events.trash()
});
}
if (controls.trash) {
buttonElements.trash = createControlButton('trash', {
container: controlGroup,
className: Constants.classes.CONTROL_BUTTON_TRASH,
title: 'Delete',
onActivate: () => {
ctx.events.trash();
}
});
}
if (controls.combine_features) {
buttonElements.combine_features = createControlButton('combineFeatures', {
container: controlGroup,
className: Constants.classes.CONTROL_BUTTON_COMBINE_FEATURES,
title: 'Combine',
onActivate: () => {
ctx.events.combineFeatures();
}
});
}
if (controls.uncombine_features) {
buttonElements.uncombine_features = createControlButton('uncombineFeatures', {
container: controlGroup,
className: Constants.classes.CONTROL_BUTTON_UNCOMBINE_FEATURES,
title: 'Uncombine',
onActivate: () => {
ctx.events.uncombineFeatures();
}
});
}
return controlGroup;
}
function removeButtons() {
Object.keys(buttonElements).forEach((buttonId) => {
const button = buttonElements[buttonId];
if (button.parentNode) {
button.parentNode.removeChild(button);
}
delete buttonElements[buttonId];
});
}
return {
setActiveButton,
queueMapClasses,
updateMapClasses,
clearMapClasses,
addButtons,
removeButtons
};
}