Closed xintongxia closed 3 years ago
@heshan0131 @rolyatmax
Nice! I think this could work, looking forward to playing with this.
Few questions since Pessimistress asked to provice feedback:
DRAW_*
modes also allow dragging vertices around?styles
- are these purely overrides? Will react-map-gl provide default styles?onUpdate
and using that to move back in history?This proposal is great! Thanks for putting this together - and especially for including a wonderful example!
A few initial thoughts/questions:
The example has a geometries
prop, while the proposal names a features
prop. I'm guessing this is just a typo in the example?
I wonder if users might also need custom styling for features the mouse is hovering over?
To make sure I'm clear on the difference between a point and a vertex, I'm assuming a point refers to the GeoJSON feature, while a vertex is a coordinate in the geometry of a path or polygon GeoJSON feature? Does a point feature contain a single vertex?
Will this component support drawing multi-polygons or polygons with holes?
Users might want to apply custom styling to features that are currently being drawn, and in some common cases, these stylings might be relatively complex, taking into account the mouse position. For example, one common polygon-drawing treatment I've noticed is where, after selecting 2 vertices, the application shows a sort of "polygon preview" with the mouse position functioning as a temporary third vertex. I imagine this might be difficult to implement with the proposed API, especially if this preview is meant to be styled differently from other polygons on the map.
Related to number 5, I imagine another common need would be to give different styles to features of the same type. For example, I might want to draw several geofences on a map and have each geofence be a different color.
I'm curious to hear about how the delete functionality would work. Would this component contain a bit of UI (e.g. a "delete" button) for the user to remove a feature?
Thanks again for putting this together! Hope I didn't give too much feedback there. Looking forward to hearing your thoughts!
styles
- are these purely overrides?
My understanding of the plan is to provide both JS styling and classname-based styling. The JavaScript styles
object will be merged with the default styles.
The example has a
geometries
prop
Corrected.
I'm assuming a point refers to the GeoJSON feature, while a vertex is a coordinate in the geometry of a path or polygon GeoJSON feature?
Yes.
This is fantastic! Thanks for putting this together.
In terms of functionality I think it looks pretty comprehensive, though I'm also wondering about the ability to drag vertices once they're created.
I also wanted to double check my understanding of how geometry drawn on the proposed overlay would relate to other geometry being rendered by the map. In our use case, we want users to draw on the map and then persist their drawn geometry such that it can be rendered by the map once the user leaves draw mode. So, if I'm understanding correctly, a full draw workflow under the current proposal might look like this:
features
state would need to be updated with whatever styling the user settled onmapStyle
propWhich I think would be a reasonable workflow-- I just wanted to make sure I understand where the responsibilities of the draw overlay end and the underlying map begin.
Thanks again for your work on this, and I'm looking forward to playing around with the overlay!
- Will
DRAW_*
modes also allow dragging vertices around?
I think it is not possible to support drawing and dragging at the same time, for example while drawing a polygon, when the user interacts with a vertex that is already drawn, DrawControl
cannot decide the user's intention is to close the polygon or to drag the vertex.
- How does selecting vertices work? I don't see a special callback/argument that deals with what vertex is selected.
I am thinking of changing DrawControl.SELECT_VERTEX
to DrawControl.EDIT_VERTEX
, as most of time when user interacts with an existing vertex, the user intends to drag the vertex.
- An interesting usability function is an undo button while drawing/editing. Could this be implemented by storing a history of states in
onUpdate
and using that to move back in history?
We are not going to include this for the initial release. But I agree with you, this is an interesting feature, we probably will leverage it in future.
@goldpbear Your workflow looks about right to me. The only thing I would like to bring attention to is that the proposed DrawControl renders an SVGOverlay, so there are these limitations:
- Will this component support drawing multi-polygons or polygons with holes?
We do not include multi-polygons or polygons with holes for the initial release. But I will investigate how to implement these features.
- I wonder if users might also need custom styling for features the mouse is hovering over?
- Users might want to apply custom styling to features that are currently being drawn, and in some common cases, these stylings might be relatively complex, taking into account the mouse position. For example, one common polygon-drawing treatment I've noticed is where, after selecting 2 vertices, the application shows a sort of "polygon preview" with the mouse position functioning as a temporary third vertex. I imagine this might be difficult to implement with the proposed API, especially if this preview is meant to be styled differently from other polygons on the map.
- Related to number 5, I imagine another common need would be to give different styles to features of the same type. For example, I might want to draw several geofences on a map and have each geofence be a different color.
I am thinking to change the styles
API, allow user to pass in either a map of style objects as mentioned in this proposal, or a function which receives the following parameters.
styles({vertex, feature, selected, ...})
- I'm curious to hear about how the delete functionality would work. Would this component contain a bit of UI (e.g. a "delete" button) for the user to remove a feature?
Thanks for pointing out. I am going to remove onDelete
callback from this proposal. Since there is already onSelect
callback, the users could easily implement their own deleting logic.
LGTM, couple questions.
mode: does it make sense to support draw rectangle? It is common to drag and draw a rectangle then select feature based on whether they intersect with it
Agree that users might want to apply custom styling to features that are currently being drawn. But there seems to be no way to know which feature is currently being edited besides listening on theonUpdate
call back.
A path and a polygon is technically the same thing, people start by drawing path, once a path is closed it becomes a polygon. I wonder having 2 separate draw modes is necessary.
- mode: does it make sense to support draw rectangle? It is common to drag and draw a rectangle then select feature based on whether they intersect with it
Agreed, will also support drawing rectangle in this DrawControl
.
- Agree that users might want to apply custom styling to features that are currently being drawn. But there seems to be no way to know which feature is currently being edited besides listening on the
onUpdate
call back.
I am thinking, styles
prop could be a callback function, which will receive the selected
status of a feature, then user can dynamically decide styles.
In the DrawControl
, only one feature could be selected and editable at one time.
- A path and a polygon is technically the same thing, people start by drawing path, once a path is closed it becomes a polygon. I wonder having 2 separate draw modes is necessary.
Yes, I think you are right. We don't really need differentiate DRAW_PATH
and DRAW_POLYGON
mode.
It might still be useful to differentiate between polygon and path in order to close the polygon automatically when the user is done editing. It seems like it might be difficult for the user to add a vertex at the exact point to close the path, but maybe this is not an issue.
Adding some thoughts on the relation to nebula.gl and the fact that we are creating two features with overlapping functionality:
@georgios-uber @supersonicclay Could make sense for the nebula team to keep an eye on this RFC. It would for instance be nice if the API/functionality remains a reasonably clean subset of nebula.gl, facilitating a seamless upgrade path to nebula.gl for users who start with this feature once more advanced features become needed.
@xintongxia I think it would be neat if the docs of this react-map-gl feature linked to nebula.gl and gave some recommendations when to use which version: https://github.com/uber/nebula.gl/blob/master/docs/overview.md
nebula.gl has already done the reciprocal doc update, I paste the current overview text in nebula.gl.
nebula.gl provides editable and interactive map overlay layers, built using the power of deck.gl.
nebula.gl aspires to be an ultra-performant, fully 3D-enabled GeoJSON editing system primarily focused on geospatial editing use cases.
Polygon
to MultiPolygon
when addition polygons are added.You should strongly consider nebula.gl:
deck.gl
or react-map-gl
.You may want to look at alternatives if:
If nebula.gl is more than what you need (e.g. in terms of bundle size), and you may want to look at other solutions, e.g. the simple polygon editor overlay being developed in react-map-gl.
That said, if you are already using deck.gl
the additional overhead of nebula.gl is small, and the seamless integration with deck.gl should be valuable.
It might still be useful to differentiate between polygon and path in order to close the polygon automatically when the user is done editing. It seems like it might be difficult for the user to add a vertex at the exact point to close the path, but maybe this is not an issue.
This was the first impression I got from playing with the mapbox-gl-draw demo. Having the option to skip redundant clicking would be nice.
Is there any chance we can add a free-hand drawing mode? The workflow could be
This module is now a submodule of nebula.gl. The nebula team have an extensible draw mode system and are implementing many draw modes that users can choose from.
The idea is that those editing modes will be made compatible not only with nebula's main module (the editable deck.gl layers) but also with this little React component.
For quickest response, recommend asking this and other related questions in the nebula.gl repo.
We have a feature request for free-hand drawing in nebula.gl. It's here: https://github.com/uber/nebula.gl/issues/172
@xintongxia can you add this rfc to nebula repo and .md file?
RFC: DrawControl
Background
react-map-gl currently does not support drawing functions. However, we have got a couple of users interested in this capability. Also it is one of P0 features on Kepler.gl 2019 roadmap.
Although Mapbox/mapbox-gl-draw provides quite nice drawing and editing features, because of its manipulating internal states, it cannot work well with React / Redux framework and therefore cannot be integrated with
react-map-gl
. vis.gl offers another geo editing library Nebula.gl, but it is an overkill while adding heavy dependencies such as deck.gl.Proposal
react-map-gl
can provide aDrawControl
, starts from simple functions like the following.Options
mode
(String, Optional) -react-map-gl
is stateless, user has complete control of themode
.DrawControl.READ_ONLY
- Not interactive. This is the default mode.DrawControl.SELECT_FEATURE
- Lets you select, delete, and drag features.DrawControl.SELECT_VERTEX
- Lets you select, delete, and drag vertices; and drag features.DrawControl.DRAW_PATH
- Lets you draw a LineString feature.DrawControl.DRAW_POLYGON
- Lets you draw a Polygon feature.DrawControl.DRAW_POINT
- Lets you draw a Point feature.styles
(Object, Optional) - A map of style objects passed to DOM elements. The following keys are supported.point
- SVG circle element.path
- SVG path element.polygon
- SVG path element.vertex
- SVG circle elementselectedVertex
selectedPoint
selectedPath
selectedPolygon
clickRadius
(Number, Optional) - Radius to detect features around a clicked point. Default is0
.features
(Array, Optional) - A list of GeoJSON Point, LineString, or Polygon features.selectedId
(String, Optional) - id of the selected feature.DrawControl
assigns a unique id to each feature which is stored infeature.properties.id
.onSelect
(Function, Required) - callback when a feature is selected. Receives one argumentselectedId
.onUpdate
(Function, Required) - callback when anything is updated. Receives one argumentfeatures
that is the updated list of GeoJSON features.onAdd
(Function, Optional) - callback when a new feature is finished drawing. Receives one argumentfeatureId
.onDelete
(Function, Optional) - callback when a feature is being deleted. Receives one argumentfeatureId
.Code Example
Compare with
mapbox-gl-draw
DrawControl
is a stateless component. To manipulate the features, simply change thefeatures
prop. This is different from calling the class methods ofMapboxDraw
.DrawControl
does not contain UI for mode selection, giving user application the flexibility to control their user experience.MapboxDraw
that are not planned for the initial release ofDrawControl
: keyboard navigation, box select.