Possible to programmatically create a vertex on SketchViewModel ArcGIS JS API 4.11+?

1135
4
Jump to solution
08-14-2019 01:05 PM
CM1
by
New Contributor II

I am wondering if it is possible to programmatically call the create/vertex add method on a sketch view model Create Polygon to live update the temp graphics layer that is shown as a feature is being drawn.  I have tried directly changing the sketchViewModel.createGraphic property to include the new geometry but the change doesn't seem to stick.  Anyone have experience doing similar?

Thank you.

1 Solution

Accepted Solutions
ArnoFiva
Esri Contributor

Thanks for sharing the CodePen sample! Again, subclassing or emitting events that usually originate from inside the API implementation is generally prone to breaking changes.

In the Participatory Planning app I've had the same issue with placing 3D symbols. I wanted them to snap along the designated planning area (see gif below). Again the app is listening to events being emitted by the SketchViewModel or the View itself (pointer-move), but instead of changing the SketchViewModel's behavior the app maintains a separate point-/polyline-/polygon graphic.

I believe you can go far ways with this approach, implementing your own sketch workflows on top of the SketchViewModel, without subclassing or overriding it's behavior. Also if you find the SketchViewModel's graphic interfering with your own graphics, you can always hide them by setting an invisible symbol.
Please also note that the kind of drawing aid you have in mind is likely something to be supported by the API in the future, snapping sketch geometries to existing features in the scene.

The CodePen example above creates a list of all vertices and implements the snapping itself. Much of that functionality is already provided by the geometryEngine or geometryEngineAsync, see for example the method nearestVertices. If you have many geometries in a FeatureLayer, you might want to try to narrow them down first using FeatureLayerView.queryFeatures(). The method can return features within a certain distance from a point in realtime.

The following example makes use of that in combination with the SketchViewModel:

SceneLayerView - query statistics by geometry | ArcGIS API for JavaScript 4.12

View solution in original post

4 Replies
ArnoFiva
Esri Contributor

Working on a demo app for Participatory Planing I wanted to do something similar to make sure users can only create and update graphics inside a predefined area. The source code is available open source on GitHub: https://github.com/Esri/participatory-planning

When the sketch widget creates a new graphic, there are not many ways you can interfere besides listening to the events emitted by the SketchViewModel. When updating a graphic, you do have access to the graphic and programmatically changing its geometry sticks - as you describe it above. This comes with a certain risk however as you are essentially relying on the implementation details of the SketchViewModel. This implementation is likely to change for upcoming versions of the ArcGIS API for JavaScript and therefore might break your code.

It would be interesting to understand your use case and what UI/UX problem you are trying to solve. It's possible that there is either a workaround or it's functionality we might want to provide as part of the API in the future.

For the above mentioned participatory planning app I ended up not changing the graphic/geometry of the Sketch widget directly, but maintaining a copy of what the resulting graphic will look like. That way the sketch workflow is restricting the user to draw outside the highlighted area, without relying on the implementation details of the SketchViewModel.

Hope this helps,

Arno

CM1
by
New Contributor II

Thanks Arno!  Helpful description and thanks for sharing the code.  Agreed on the whole "not wanting to dig into the implementation" aspect. 

So, implementation-wise, I am trying to do vertex snapping similar to how it is done in this sample with the Draw class: https://codepen.io/orengal/pen/qLewXd but with the SketchViewModel instead.

My latest experiments have led me to try extending the SketchViewModel with a subclass so I could emit my own create events.  The hope being that when a user clicks the map within a snap threshold I could perhaps emit and undo event and then emit my own create event and pass in the snapped vertex instead of the original vertex from the user's click event.  Does that sound doable?  Have not been able to correctly format the emit at this point I think as I am not getting the expected behavior.  

Thank you.

ArnoFiva
Esri Contributor

Thanks for sharing the CodePen sample! Again, subclassing or emitting events that usually originate from inside the API implementation is generally prone to breaking changes.

In the Participatory Planning app I've had the same issue with placing 3D symbols. I wanted them to snap along the designated planning area (see gif below). Again the app is listening to events being emitted by the SketchViewModel or the View itself (pointer-move), but instead of changing the SketchViewModel's behavior the app maintains a separate point-/polyline-/polygon graphic.

I believe you can go far ways with this approach, implementing your own sketch workflows on top of the SketchViewModel, without subclassing or overriding it's behavior. Also if you find the SketchViewModel's graphic interfering with your own graphics, you can always hide them by setting an invisible symbol.
Please also note that the kind of drawing aid you have in mind is likely something to be supported by the API in the future, snapping sketch geometries to existing features in the scene.

The CodePen example above creates a list of all vertices and implements the snapping itself. Much of that functionality is already provided by the geometryEngine or geometryEngineAsync, see for example the method nearestVertices. If you have many geometries in a FeatureLayer, you might want to try to narrow them down first using FeatureLayerView.queryFeatures(). The method can return features within a certain distance from a point in realtime.

The following example makes use of that in combination with the SketchViewModel:

SceneLayerView - query statistics by geometry | ArcGIS API for JavaScript 4.12

CM1
by
New Contributor II

Thank you so much for all the great info Arno!  Very helpful.  My colleague and I are following the "virtual graphics layer" procedure you recommended (in combination with the geometry engine) and that seems to be working.  Much appreciated!  When we get it working fully, can share out some snippets to help others.

0 Kudos