Mapbox Draw Circle on Map

When our apps need a spider web map, we turn to MapboxGL, a cut-edge open source mapping library that allows us to build fast, beautiful maps. Not too long later nosotros started tinkering with MapboxGL, nosotros were faced with the demand to let the user draw polygons. Enter mapbox-gl-describe, an add-on to MapboxGL that gives you some simple describe controls, renders shapes on the screen every bit the user draws a betoken, line, or polygon, and gives you lot some nice event hooks.

Y'all can run into mapbox-gl-depict in action in ZoLa's measurement tool:

In this example, we're all the same using the out-of-the-box functionality of the draw tools simply have added a custom control to choose between line and polygon way, and a UI for displaying the measurement (and switching units!).

We recently encountered a need to have the user select geometries on a web map by radius from a center point. Mapbox-gl-depict does not include a circle-cartoon mode.

One approach would be to have the user select a center point, then enter a radius using a text input, merely it would be better if the user could see the circle they are defining as they define it, only like they tin with the polygon and line tools.

What's a radius, really? Well, it'southward a line, and mapbox-gl-draw already has a line tool. So, what nosotros need to exercise is modify the line tool with the following rules:

  1. The user'southward kickoff click is the center point
  2. As the user moves the arrow, render both the line betwixt the middle point and the arrow, and the circumvolve that they are defining.
  3. The user'southward second click always ends the drawing.
  4. When drawing is complete, the resulting GeoJSON is a Point feature for the middle point, with a radius property.

Hither's what information technology looks similar in our app:

Using the custom radius mode to select census tracts

How we built it

Afterward some snooping, we discovered that mapbox-gl-describe allows yous to define custom drawing modes, and has a nice markdown file all about it. We didn't want to start from scratch, and so we decided to hijack the Line mode.

          const describe = new MapboxDraw({
displayControlsDefault: false,
styles: drawStyles,
modes: Object.assign({
draw_radius: RadiusMode,
}, MapboxDraw.modes),
});

Nosotros instantiate mapbox-gl-draw using a modes holding in the options. RadiusMode is our new custom mode which is really just the built-in line mode that's been modified to meet our needs.

To create RadiusMode, we started with importing the existing line tool.

          const RadiusMode = MapboxDraw.modes.draw_line_string;        

Then we ascertain new functions for some of the line tool's event listeners, in club to achieve the rules described above.

Rule #1 works out of the box: the beginning click will set the showtime vertex of the line.

For rule #two, nosotros get half of the functionality for costless considering the line tool already draws the line betwixt the first vertex and the pointer. To draw the circle, we actually stop up cartoon a circle-like polygon.

RadiusMode.toDisplayFeatures() is chosen with each movement of the mouse, and fires display() for each GeoJSON feature that should be displayed in existent time. The existing line tool displays the vertices and the line, and then nosotros added 1 more to display the circle-like polygon.

          const circleFeature = createGeoJSONCircle(center, radiusInKm, state.line.id);          display(circleFeature);        

Creating the circle-like polygon was simple using an algorithm we found in this Stack Overflow mail. Given a center betoken and radius in kilometers, it creates a 64-indicate polygon that resembles a circumvolve.

          role createGeoJSONCircle(center, radiusInKm, parentId, points = 64) {
const coords = {
latitude: heart[i],
longitude: center[0],
};
const km = radiusInKm; const ret = [];
const distanceX = km / (111.320 * Math.cos((coords.latitude * Math.PI) / 180));
const distanceY = km / 110.574;
let theta;
let x;
allow y;
for (allow i = 0; i < points; i += 1) {
theta = (i / points) * (2 * Math.PI);
x = distanceX * Math.cos(theta);
y = distanceY * Math.sin(theta);
ret.push([coords.longitude + x, coords.latitude + y]);
}
ret.button(ret[0]);
render {
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [ret],
},
properties: {
parent: parentId,
},
};
}

We had originally attempted to use a MapboxGL circumvolve marker, but by using a circle-like polygon the feature nonetheless remains authentic fifty-fifty if the map is pitched!

For the best user experience when drawing a radius, we also added a label layer to the map showing the in-progress radius in both standard and metric formats. Nosotros borrowed the aforementioned logic for switching from meters to kilometers, and anxiety to miles as was used in ZoLa's drawing tool.

The final stride was to hijack RadiusMode.clickAnywhere() to force drawing to stop after the second click (rule #three above). clickAnywhere(), as the proper noun suggests, is called when the user clicks anywhere afterward drawing begins.

          RadiusMode.clickAnywhere = role(state, e) {
// this ends the cartoon subsequently the user creates a 2nd signal, triggering this.onStop
if (state.currentVertexPosition === 1) {
state.line.addCoordinate(0, eastward.lngLat.lng, e.lngLat.lat);
render this.changeMode('simple_select', { featureIds: [state.line.id] });
}
...
// default click handling remains the aforementioned, adding the vertex to the state.
}

There'south a bit more than to it, merely those are the highlights. In our app, we utilise the GeoJSON Point feature created by the drawing tools to do an ST_Dwithin() query in PostGIS, selecting polygons that are inside the specified distance of the heart point.

Y'all can inspect the full RadiusMode module hither, and come across it in activity in our NYC Population Factfinder census data tool. We hope this volition exist a useful starting betoken for anyone thinking of extending a mapbox-gl-draw mode or writing their own.

Happy hacking!

dildygoisibew66.blogspot.com

Source: https://medium.com/nyc-planning-digital/building-a-custom-draw-mode-for-mapbox-gl-draw-1dab71d143ee

0 Response to "Mapbox Draw Circle on Map"

إرسال تعليق

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel