27.01.2021 | Christian Zielke | comment icon 0 Comment

Customize react-leaflet-draw

You are using React? You want to implement the functionality to draw on a map? You are already using react-leaflet-draw, but want to customize some things?

Screenshot of the demo project
Screenshot of the demo project (see here: https://github.com/chritsian/custom-button-react-leaflet-draw)

When your answer to the first two questions is yes, the next section of this article will give you advice which possibilities react-leaflet-draw and leaflet-draw offer you, but other frameworks are not taken into account. Your answer to all three questions is yes? So, we assume you already have a working react-leaflet-draw implementation or at least some react-leaflet-draw knowledge. Possibly you are facing similar problems we did during customizing react-leaflet-draw. That is why we wrote this article to give other developers an overview of how you can customize react-leaflet-draw. The third section of this article deals with the problem: how to customize the EditControl Buttons? In the fourth paragraph we present further approaches to customize react-leaflet-draw.

When to use react-leaflet-draw

The react-leaflet-draw plugin (see here) is easily to include into an application. But the question is what functionality do we get? The user interaction is nearly identical to the leaflet-draw demo which is shown at the screenshot below (see here). You can choose which of the shapes should be available and have several styling options. Unfortunately, they are not documented very well. Furthermore, you have the option to define methods you hand over to hook functions. For example, if you want to perform an action after a polygon is drawn.

Screenshot of the leaflet-draw demo
Screenshot of the leaflet-draw demo

So, what do you get using react-leaflet-draw? A React component with the standard leaflet-draw toolbar, customization of the drawn shapes and the possibility to provide methods for all leaflet-draw events. If you are satisfied with this functionality react-leaflet-draw will be perfect for you.

So, when should you not use it? The answer is quite simple: if you want more functionality than explained above, do not use react-leaflet-draw! Otherwise you must use some of the workarounds we discuss later. If you start from scratch and do not like the style of the default leaflet-draw sidebar we recommend to build your own approach using leaflet-draw which you can use much more flexible or you can use a fork of leaflet-draw which you can customize a lot more.

Long story short: Look at the linked demo, if this fulfills your need use react-leaflet-draw otherwise go with leaflet-draw.

Access the EditControl handlers

React-leaflet-draw works with a toolbar called EditControl which is a React component. We can refer to this component using the React Hook useRef. In the following we will call this reference editRef. Our approach is to access the EditControl handlers using this reference. Leaflet-draw works with three handlers: draw, edit and remove. Each of them is represented as a button in the standard toolbar. For more details look at the leaflet-draw documentation (see here). If we can access these handlers, we can call every method, listed in the leaflet-draw documentation, with a custom UI. For polygon drawing, editing or deletion (other shapes work the same way) we can access the handlers the following way:

In the following we demonstrate the usage with a customization for polygon drawing. Polygon drawing starts with a call to enable() and is stopped by calling disable(). Before disabling the draw handler, completeShape() has to be called to save the polygon. Otherwise the polygon drawing gets canceled. Assuming we have a button to start and save the drawing the following click handler would fulfill the desired actions:

Deletion of the last drawn vertex can be performed with the call deleteLastVertex(). To start editing a drawn polygon call enable() on the edit handler. To save it call save() and afterwards disable(). To cancel the edit call disable() without prior saving. The deletion handler works the same way the edit handler does. Edit and remove handler work the same way for every shape. Only the draw handler needs to be called depending on the desired shape. The following is an overview of the described methods calls.

The knowledge which method is the right method to preform an action with and an overview which actions are possible are documented in the leaflet-draw documentation (see here). We also provide the described example as a GitHub repository (see here). To run the example clone the repository, run npm install and npm start. Then you can play around by changing the click listener, add buttons etc. You will notice that the toolbar is still visible and clickable. This is good for the example as long as we do not cover every action with a custom UI. If you only want additional controls or only customize a part of actions that is fine. Otherwise you can hide the EditControl via the leaflet-draw.css.

Further customization approaches

Click and contextmenu

A nice way to interact with the map UI is to bind actions directly to the drawn shapes. To bind an action to a drawn shape we can implement a method which is called from the EditControls onCreated hook. For example, bind a click event which enables the edit mode to every drawn shape. Another use case could be to show detailed information about the clicked shape.

Talking about click actions you possibly want to customize the right click (context menu). For drawn shapes we can do this as described above (contextmenu instead of click). If we want to perform right click actions in drawing mode, for example finish the drawing with a right click, we will run into problems because leaflet-draw does not distinguish between left and right click events. We have two options to solve this problem. The first one is to fork leaflet-draw and replace the click events. This is quite an overkill regarding the changed behavior, but it would be the cleanest solution. The second option is to delete the click handlers from the layer/map and add new handlers. The events we must delete are: mousedown, mouseup and touchstart. We could not find out from which layer we have to delete them in specific, therefore we just deleted all listeners from all layers. Of course, this can lead to problems if you want to draw multiple shapes. Then you must figure out which specific layer needs to be modified.

Tooltips

React-leaflet-draw comes with predefined tooltips. We can change their texts using the L.drawLocal Object (see here). If we want to add additional tooltips we can do this via the bindTooltip function. For example, we want to add a tooltip to a drawn polygon with the hint that a click on it would open the edit mode.

So far, the tooltip will be visible but without leaflet-draw style. To achieve this, we have to import leaflet.css and leaflet.draw.css into our application. Loading them from source causes problems and will not override the styles. To get the leaflet-draw tooltip style, changes in the leaflet-draw.css are necessary. These two styles must be added to the leaflet-draw.css:

To get the style displayed correct we have to call the styles in the same order as below. The sticky and direction option are a matter of taste. They are just mentioned here for compatibility to the GitHub example (see here).

customize leaflet leaflet draw react react leaflet draw

Leave a Comment