-
Notifications
You must be signed in to change notification settings - Fork 590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
can I use my custom control bar to draw? #874
Comments
You can simply use That, with hiding the default bar controls would do the trick. You can also make a monkey patch (demo) to add more buttons to the bar : var draw = new MapboxDraw();
var drawBar = new extendDrawBar({
draw: draw,
buttons: [
{
on: 'click',
action: save,
classes: ['fa', 'fa-floppy-o']
}
]
});
map.addControl(drawBar, 'top-left');
/**
* Helpers
*/
function save() {
console.log('saved');
}
/**
* Patch
*/
class extendDrawBar {
constructor(opt) {
let ctrl = this;
ctrl.draw = opt.draw;
ctrl.buttons = opt.buttons || [];
ctrl.onAddOrig = opt.draw.onAdd;
ctrl.onRemoveOrig = opt.draw.onRemove;
}
onAdd(map) {
let ctrl = this;
ctrl.map = map;
ctrl.elContainer = ctrl.onAddOrig(map);
ctrl.buttons.forEach((b) => {
ctrl.addButton(b);
});
return ctrl.elContainer;
}
onRemove(map) {
let ctrl = this;
ctrl.buttons.forEach((b) => {
ctrl.removeButton(b);
});
ctrl.onRemoveOrig(map);
}
addButton(opt) {
let ctrl = this;
var elButton = document.createElement('button');
elButton.className = 'mapbox-gl-draw_ctrl-draw-btn';
if (opt.classes instanceof Array) {
opt.classes.forEach((c) => {
elButton.classList.add(c);
});
}
elButton.addEventListener(opt.on, opt.action);
ctrl.elContainer.appendChild(elButton);
opt.elButton = elButton;
}
removeButton(opt) {
opt.elButton.removeEventListener(opt.on, opt.action);
opt.elButton.remove();
}
} I just started to use it. There is maybe a better way. |
@fxi thoughts on having buttons be setupable via |
Yep, a PR with a proper way of doing that could be more useful than the thing I wrote. |
@tomasdev Does this mean we cannot right now use the default |
hello , how I can add an icone with the patch monkey |
@Aliber009 You should probably use modes instead – but as you ask : [...]
// add a save button using the "monkey patch"
const draw = new MapboxDraw();
const drawBar = new extendDrawBar({
draw: draw,
buttons: [{
on: 'click',
action: ()=>{ alert('🐒')},
// Here ⤵️⤵️⤵️⤵️ you can change classes. E.g. using font awesome classes or your own.
classes: ['fa', 'fa-floppy-o']
}]
});
map.addControl(drawBar); Or you can modify the patch to add text content : |
Hi there! From my understanding, the modes property only allows you to select togglable modes. Controls to be displayed on the toolbar can only be selected from existing controls (draw polygon, line, trash etc). Custom Controls cannot be added to the toolbar. Or should I define the icon associated to the custom control somewhere in the definition of that control? const modes = MapboxDraw.modes
modes['draw_rectangle'] = DrawRectangle;
// ...
<MapboxDraw>
modes={modes}
displayControlsDefault={false}
controls={{
polygon: true,
trash: true,
// rectangle: true // custom control display
}}
</MapboxDraw> Adding rectangle to the controls property results in this error: Edit: seems this is because the DrawRectangle custom control does not implement |
Thanks it worked |
Hello, I'm trying to simply give all the functionality of the draw_polygon button to a new custom button. It just seems like it can be hard to understand its functionality, replacing this icon with the word/text = "Draw" might be more intuitive for the regular user. Any guidance on how I can accomplish this functionality?, thank you ahead of time |
HI All, Can i create a CUSTOM Button and call the delete function to delete the drawn polygon, |
For those looking to build their own custom control UI, it looks like this is already doable. Example: hide the buttons and render your own: let map; // get/construct your Mapbox instance
const draw = new MapboxDraw({
// don't render the default controls
displayControlsDefault: false,
});
// position probably doesn't matter.
map.addControl(draw, 'top-left')
// track current mode so you can set active status on custom control buttons
let drawMode = draw.getMode();
map.on("draw.modechange", (e) => (drawMode = e.mode));
// example polygon button click handler.
// add this to your custom rendered controller's polygon button
function handleSelectPolygonMode () {
draw.changeMode(draw.modes.DRAW_POLYGON)
// draw.changeMode() doesn't appear to properly trigger map.on('draw.changemode')
// so we need to manually update our cached mode here
drawMode = draw.modes.DRAW_POLYGON;
// or you could make it a toggle button
if (drawMode === draw.modes.DRAW_POLYGON) {
drawMode = draw.modes.SIMPLE_SELECT;
} else {
drawMode = draw.modes.DRAW_POLYGON;
}
draw.changeMode(drawMode);
} |
This shows only the click handler, but how do you actually render a custom button with that click handler attached to it? |
I have a working example here: I’m adding a custom button do draw rectangles, but it can do anything you want. 🚨 Open the map preview in a NEW WINDOW to see the custom draw bar on the map. When opened side by side with the code, Stackblitz can’t display the draw bar. |
Here's a React-based solution that avoids a lot of rigmarole. I ran partially with @joel-daros's solution by overriding import { default as _MapboxDraw } from "@mapbox/mapbox-gl-draw";
class MapboxDraw extends _MapboxDraw {
_container: HTMLElement | undefined;
constructor(props: DrawControlProps) {
super(props);
const onAdd = this.onAdd;
this.onAdd = (map: mapboxgl.Map) => {
this._container = onAdd(map);
return this._container;
};
}
}
type DrawControlProps = {
position?: ControlPosition;
drawOptions?: MapboxDraw.MapboxDrawOptions;
};
function DrawControl(props: DrawControlProps) {
const [container, setContainer] = useState<HTMLElement | undefined>(undefined);
const control = useControl(
() =>
new MapboxDraw({
...props.drawOptions,
displayControlsDefault: false,
}),
{ position: props.position },
);
useEffect(() => {
if (!container && control._container) {
setContainer(control._container);
}
}, [control, container]);
return container
? createPortal(
<>
<button
title="Polygon tool (p)"
className="mapbox-gl-draw_ctrl-draw-btn mapbox-gl-draw_polygon"
onClick={() => control.changeMode("draw_polygon")}
/>
</>,
container,
)
: null;
} |
hi, can I use my custom control bar to draw, not use the MapboxDraw's controls? thanks
The text was updated successfully, but these errors were encountered: