This sample demonstrates how to update a polygon geometry of a graphic by only reshaping or moving it using SketchViewModel.
How it works
The application initializes the Sketch
with the following parameters.
// Create a new instance of sketchViewModel
sketchViewModel = new SketchViewModel({
view: view,
layer: graphicsLayer,
updateOnGraphicClick: false,
defaultUpdateOptions: {
// set the default options for the update operations
toggleToolOnClick: false // only reshape operation will be enabled
}
});
This application only allows move
and reshape
operations for the graphics when it is being updated. It does not allow scale
or rotate
operations. This is done by listening to MapView's click event and having a custom hitTest logic to select and update the graphic of interest.
When a user clicks on the new development graphic, the SketchViewModel's update() method is called with the graphic and reshape
tool as its parameters. This will ensure that the only allowed update operations for the graphic is to move
or reshape
.
// This function is called when a user clicks on the view.
function setUpGraphicClickHandler() {
view.on("click", (event) => {
// check if the sketch's state active if it is then that means
// the graphic is already being updated, no action required.
if (sketchViewModel.state === "active") {
return;
}
view.hitTest(event).then((response) => {
const results = response.results;
// Check if the new development graphic was clicked and pass
// the graphic to sketchViewModel.update() with reshape tool.
results.forEach((result) => {
if (
result.graphic.layer === sketchViewModel.layer &&
result.graphic.attributes &&
result.graphic.attributes.newDevelopment
) {
sketchViewModel.update([result.graphic], { tool: "reshape" });
}
});
});
});
}
As a user is moving or reshaping the graphic, the application constantly checks if the updated graphic intersects school buffers or is still contained by the boundary polygon. If the new location for the graphic is not allowed, the graphic's symbol is changed to a red color indicating this reshape or move operation is not allowed. If a user tries to cancel or complete the update operation while the updated graphic is invalid, the sketchViewModel's update() method is called again with the invalid graphic and reshape
tool. This gives the user a chance to correct any invalid updates.
// Listen to sketchViewModel's update event to do
// graphic reshape or move validation
sketchViewModel.on("update", onGraphicUpdate);
function onGraphicUpdate(event) {
// get the graphic as it is being updated
const graphic = event.graphics[0];
// check if the graphic is intersecting school buffers or is
// still contained by the boundary polygon as the graphic is being updated
intersects = geometryEngine.intersects(buffers, graphic.geometry);
contains = geometryEngine.contains(boundaryPolygon, graphic.geometry);
// change the graphic symbol to valid or invalid symbol
// depending the graphic location
graphic.symbol = intersects || !contains ? invalidSymbol : validSymbol;
// check if the update event's the toolEventInfo.type is move-stop or reshape-stop
// then it means user finished moving or reshaping the graphic, call complete method.
// this will change update event state to complete and we will check the validity of the graphic location.
if (
event.toolEventInfo &&
(event.toolEventInfo.type === "move-stop" || event.toolEventInfo.type === "reshape-stop")
) {
if (contains && !intersects) {
sketchViewModel.complete();
}
} else if (event.state === "complete") {
// graphic moving or reshaping has been completed or cancelled (distinguish with aborted property)
// if the graphic is in an illegal spot, call sketchviewmodel's update method again
// giving user a chance to correct the location of the graphic
if (!contains || intersects) {
sketchViewModel.update({
tool: "reshape",
graphics: [graphic]
});
}
}
}