I am trying to have a simple map and:
I looked at this widget https://developers.arcgis.com/javascript/latest/sample-code/sketch-geometries/ but could not figure out how to limit it to one geometry in the graphics layer. I assume that I could just remove all features every time the user clicks the map. Or someway to disable the widget after each feature creation in the map (Then deleting all features next time the widget is used?)
I am not sure the widget is the way to go and looking for some thoughts or examples for this.
The widget stores geometry in the graphics layer so If I could control the layer to only have 1 feature at a time I could query the graphics layer for its geometry....
Thoughts?
Solved! Go to Solution.
Got it... Sorry to waste your time... If anyone can benefit then great..
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Draw polyline | Sample | ArcGIS API for JavaScript 4.24</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.24/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.24/"></script>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/views/draw/Draw",
"esri/Graphic",
"esri/geometry/geometryEngine"
], (Map, MapView, Draw, Graphic, geometryEngine) => {
const map = new Map({
basemap: "gray-vector"
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 15,
center: [18.06, 59.34]
});
// add the button for the draw tool
view.ui.add("line-button", "top-left");
view.ui.add("point-button", "top-left");
view.ui.add("polygon-button", "top-left");
const draw = new Draw({
view: view
});
document.getElementById("point-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("point");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// PointDrawAction.cursor-update
// Give a visual feedback to users as they move the pointer over the view
action.on("cursor-update", function (evt) {
updateVerticesPoint(evt.coordinates);
});
// PointDrawAction.draw-complete
// Create a point when user clicks on the view or presses "C" key.
action.on("draw-complete", function (evt) {
updateVerticesPoint(evt.coordinates);
});
};
document.getElementById("polygon-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polygon");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen polylineDrawAction events to give immediate visual feedback
// to users as the line is being drawn on the view.
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesPolygon
);
};
// draw polyline button
document.getElementById("line-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polyline");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen polylineDrawAction events to give immediate visual feedback
// to users as the line is being drawn on the view.
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesLine
);
};
function updateVerticesPoint(coordinates) {
//// create a polyline from returned vertices
//if (event.vertices.length > 0) {
// const result = createGraphicPoint(event);
//}
view.graphics.removeAll();
let point = {
type: "point", // autocasts as /Point
x: coordinates[0],
y: coordinates[1],
spatialReference: view.spatialReference
};
let graphic = new Graphic({
geometry: point,
symbol: {
type: "simple-marker", // autocasts as SimpleMarkerSymbol
style: "square",
color: "red",
size: "16px",
outline: { // autocasts as SimpleLineSymbol
color: [255, 255, 0],
width: 3
}
}
});
view.graphics.add(graphic);
}
// Checks if the last vertex is making the line intersect itself.
function updateVerticesPolygon(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphicPolygon(event);
}
}
function updateVerticesLine(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphicLine(event);
// if the last vertex is making the line intersects itself,
// prevent the events from firing
if (result.selfIntersects) {
event.preventDefault();
}
}
}
function createGraphicPoint(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicPoly = new Graphic({
geometry: {
type: "point",
spatialReference: view.spatialReference
},
symbol: {
type: "simple-marker", // autocasts as new SimpleFillSymbol
color: [227, 139, 79, 0.8],
outline: {
color: [255, 255, 255],
width: 1
}
}
});
view.graphics.add(graphicPoly);
}
// create a new graphic presenting the polyline that is being drawn on the view
function createGraphicPolygon(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicPoly = new Graphic({
geometry: {
type: "polygon",
rings: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol
color: [227, 139, 79, 0.8],
outline: {
color: [255, 255, 255],
width: 1
}
}
});
view.graphics.add(graphicPoly);
}
function createGraphicLine(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicLine = new Graphic({
geometry: {
type: "polyline",
paths: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-line", // autocasts as new SimpleFillSymbol
color: [4, 90, 141],
width: 4,
cap: "round",
join: "round"
}
});
// check if the polyline intersects itself.
const intersectingSegment = getIntersectingSegment(graphicLine.geometry);
// Add a new graphic for the intersecting segment.
if (intersectingSegment) {
view.graphics.addMany([graphicLine, intersectingSegment]);
}
// Just add the graphic representing the polyline if no intersection
else {
view.graphics.add(graphicLine);
}
// return intersectingSegment
return {
selfIntersects: intersectingSegment
};
}
// function that checks if the line intersects itself
function isSelfIntersecting(polyline) {
if (polyline.paths[0].length < 3) {
return false;
}
const line = polyline.clone();
//get the last segment from the polyline that is being drawn
const lastSegment = getLastSegment(polyline);
line.removePoint(0, line.paths[0].length - 1);
// returns true if the line intersects itself, false otherwise
return geometryEngine.crosses(lastSegment, line);
}
// Checks if the line intersects itself. If yes, change the last
// segment's symbol giving a visual feedback to the user.
function getIntersectingSegment(polyline) {
if (isSelfIntersecting(polyline)) {
return new Graphic({
geometry: getLastSegment(polyline),
symbol: {
type: "simple-line", // autocasts as new SimpleLineSymbol
style: "short-dot",
width: 3.5,
color: "yellow"
}
});
}
return null;
}
// Get the last segment of the polyline that is being drawn
function getLastSegment(polyline) {
const line = polyline.clone();
const lastXYPoint = line.removePoint(0, line.paths[0].length - 1);
const existingLineFinalPoint = line.getPoint(
0,
line.paths[0].length - 1
);
return {
type: "polyline",
spatialReference: view.spatialReference,
hasZ: false,
paths: [
[
[existingLineFinalPoint.x, existingLineFinalPoint.y],
[lastXYPoint.x, lastXYPoint.y]
]
]
};
}
});
</script>
</head>
<body>
<!-- https://developers.arcgis.com/javascript/latest/esri-icon-font/ -->
<div id="viewDiv">
<div id="point-button" class="esri-widget esri-widget--button esri-interactive" title="Draw point">
<span class="esri-icon-map-pin"></span>
</div>
<div id="line-button" class="esri-widget esri-widget--button esri-interactive" title="Draw polyline">
<span class="esri-icon-polyline"></span>
</div>
<div id="polygon-button" class="esri-widget esri-widget--button esri-interactive" title="Draw polygon">
<span class="esri-icon-polygon"></span>
</div>
</div>
</body>
</html>
OK I am trying this solution... It has the Line working I am now trying to incorporate the Polygon add...
Not sure where I am failing
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Draw polyline | Sample | ArcGIS API for JavaScript 4.24</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.24/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.24/"></script>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/views/draw/Draw",
"esri/Graphic",
"esri/geometry/geometryEngine"
], (Map, MapView, Draw, Graphic, geometryEngine) => {
const map = new Map({
basemap: "gray-vector"
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 15,
center: [18.06, 59.34]
});
// add the button for the draw tool
view.ui.add("line-button", "top-left");
view.ui.add("point-button", "top-left");
view.ui.add("polygon-button", "top-left");
const draw = new Draw({
view: view
});
document.getElementById("polygon-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polygon");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen polylineDrawAction events to give immediate visual feedback
// to users as the line is being drawn on the view.
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesPolygon
);
};
// draw polyline button
document.getElementById("line-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polyline");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen polylineDrawAction events to give immediate visual feedback
// to users as the line is being drawn on the view.
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesLine
);
};
// Checks if the last vertex is making the line intersect itself.
function updateVerticesPolygon(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphicPolygon(event);
}
}
function updateVerticesLine(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphicLine(event);
// if the last vertex is making the line intersects itself,
// prevent the events from firing
if (result.selfIntersects) {
event.preventDefault();
}
}
}
// create a new graphic presenting the polyline that is being drawn on the view
function createGraphicPolygon(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicPoly = new Graphic({
geometry: {
type: "polygon",
paths: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol
color: [227, 139, 79, 0.8],
outline: {
color: [255, 255, 255],
width: 1
}
}
});
view.graphics.add(graphicPoly);
}
function createGraphicLine(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicLine = new Graphic({
geometry: {
type: "polyline",
paths: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-line", // autocasts as new SimpleFillSymbol
color: [4, 90, 141],
width: 4,
cap: "round",
join: "round"
}
});
// check if the polyline intersects itself.
const intersectingSegment = getIntersectingSegment(graphicLine.geometry);
// Add a new graphic for the intersecting segment.
if (intersectingSegment) {
view.graphics.addMany([graphicLine, intersectingSegment]);
}
// Just add the graphic representing the polyline if no intersection
else {
view.graphics.add(graphicLine);
}
// return intersectingSegment
return {
selfIntersects: intersectingSegment
};
}
// function that checks if the line intersects itself
function isSelfIntersecting(polyline) {
if (polyline.paths[0].length < 3) {
return false;
}
const line = polyline.clone();
//get the last segment from the polyline that is being drawn
const lastSegment = getLastSegment(polyline);
line.removePoint(0, line.paths[0].length - 1);
// returns true if the line intersects itself, false otherwise
return geometryEngine.crosses(lastSegment, line);
}
// Checks if the line intersects itself. If yes, change the last
// segment's symbol giving a visual feedback to the user.
function getIntersectingSegment(polyline) {
if (isSelfIntersecting(polyline)) {
return new Graphic({
geometry: getLastSegment(polyline),
symbol: {
type: "simple-line", // autocasts as new SimpleLineSymbol
style: "short-dot",
width: 3.5,
color: "yellow"
}
});
}
return null;
}
// Get the last segment of the polyline that is being drawn
function getLastSegment(polyline) {
const line = polyline.clone();
const lastXYPoint = line.removePoint(0, line.paths[0].length - 1);
const existingLineFinalPoint = line.getPoint(
0,
line.paths[0].length - 1
);
return {
type: "polyline",
spatialReference: view.spatialReference,
hasZ: false,
paths: [
[
[existingLineFinalPoint.x, existingLineFinalPoint.y],
[lastXYPoint.x, lastXYPoint.y]
]
]
};
}
});
</script>
</head>
<body>
<!-- https://developers.arcgis.com/javascript/latest/esri-icon-font/ -->
<div id="viewDiv">
<div id="point-button" class="esri-widget esri-widget--button esri-interactive" title="Draw point">
<span class="esri-icon-map-pin"></span>
</div>
<div id="line-button" class="esri-widget esri-widget--button esri-interactive" title="Draw polyline">
<span class="esri-icon-polyline"></span>
</div>
<div id="polygon-button" class="esri-widget esri-widget--button esri-interactive" title="Draw polygon">
<span class="esri-icon-polygon"></span>
</div>
</div>
</body>
</html>
OK I got the polygon to draw... Needed RINGS: vertices,
Just need to figure out the point
geometry: {
type: "polygon",
rings: vertices,
spatialReference: view.spatialReference
},
Got it... Sorry to waste your time... If anyone can benefit then great..
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<title>Draw polyline | Sample | ArcGIS API for JavaScript 4.24</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.24/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.24/"></script>
<style>
html,
body,
#viewDiv {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/views/draw/Draw",
"esri/Graphic",
"esri/geometry/geometryEngine"
], (Map, MapView, Draw, Graphic, geometryEngine) => {
const map = new Map({
basemap: "gray-vector"
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 15,
center: [18.06, 59.34]
});
// add the button for the draw tool
view.ui.add("line-button", "top-left");
view.ui.add("point-button", "top-left");
view.ui.add("polygon-button", "top-left");
const draw = new Draw({
view: view
});
document.getElementById("point-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("point");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// PointDrawAction.cursor-update
// Give a visual feedback to users as they move the pointer over the view
action.on("cursor-update", function (evt) {
updateVerticesPoint(evt.coordinates);
});
// PointDrawAction.draw-complete
// Create a point when user clicks on the view or presses "C" key.
action.on("draw-complete", function (evt) {
updateVerticesPoint(evt.coordinates);
});
};
document.getElementById("polygon-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polygon");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen polylineDrawAction events to give immediate visual feedback
// to users as the line is being drawn on the view.
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesPolygon
);
};
// draw polyline button
document.getElementById("line-button").onclick = () => {
view.graphics.removeAll();
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polyline");
// focus the view to activate keyboard shortcuts for sketching
view.focus();
// listen polylineDrawAction events to give immediate visual feedback
// to users as the line is being drawn on the view.
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesLine
);
};
function updateVerticesPoint(coordinates) {
//// create a polyline from returned vertices
//if (event.vertices.length > 0) {
// const result = createGraphicPoint(event);
//}
view.graphics.removeAll();
let point = {
type: "point", // autocasts as /Point
x: coordinates[0],
y: coordinates[1],
spatialReference: view.spatialReference
};
let graphic = new Graphic({
geometry: point,
symbol: {
type: "simple-marker", // autocasts as SimpleMarkerSymbol
style: "square",
color: "red",
size: "16px",
outline: { // autocasts as SimpleLineSymbol
color: [255, 255, 0],
width: 3
}
}
});
view.graphics.add(graphic);
}
// Checks if the last vertex is making the line intersect itself.
function updateVerticesPolygon(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphicPolygon(event);
}
}
function updateVerticesLine(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphicLine(event);
// if the last vertex is making the line intersects itself,
// prevent the events from firing
if (result.selfIntersects) {
event.preventDefault();
}
}
}
function createGraphicPoint(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicPoly = new Graphic({
geometry: {
type: "point",
spatialReference: view.spatialReference
},
symbol: {
type: "simple-marker", // autocasts as new SimpleFillSymbol
color: [227, 139, 79, 0.8],
outline: {
color: [255, 255, 255],
width: 1
}
}
});
view.graphics.add(graphicPoly);
}
// create a new graphic presenting the polyline that is being drawn on the view
function createGraphicPolygon(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicPoly = new Graphic({
geometry: {
type: "polygon",
rings: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol
color: [227, 139, 79, 0.8],
outline: {
color: [255, 255, 255],
width: 1
}
}
});
view.graphics.add(graphicPoly);
}
function createGraphicLine(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicLine = new Graphic({
geometry: {
type: "polyline",
paths: vertices,
spatialReference: view.spatialReference
},
symbol: {
type: "simple-line", // autocasts as new SimpleFillSymbol
color: [4, 90, 141],
width: 4,
cap: "round",
join: "round"
}
});
// check if the polyline intersects itself.
const intersectingSegment = getIntersectingSegment(graphicLine.geometry);
// Add a new graphic for the intersecting segment.
if (intersectingSegment) {
view.graphics.addMany([graphicLine, intersectingSegment]);
}
// Just add the graphic representing the polyline if no intersection
else {
view.graphics.add(graphicLine);
}
// return intersectingSegment
return {
selfIntersects: intersectingSegment
};
}
// function that checks if the line intersects itself
function isSelfIntersecting(polyline) {
if (polyline.paths[0].length < 3) {
return false;
}
const line = polyline.clone();
//get the last segment from the polyline that is being drawn
const lastSegment = getLastSegment(polyline);
line.removePoint(0, line.paths[0].length - 1);
// returns true if the line intersects itself, false otherwise
return geometryEngine.crosses(lastSegment, line);
}
// Checks if the line intersects itself. If yes, change the last
// segment's symbol giving a visual feedback to the user.
function getIntersectingSegment(polyline) {
if (isSelfIntersecting(polyline)) {
return new Graphic({
geometry: getLastSegment(polyline),
symbol: {
type: "simple-line", // autocasts as new SimpleLineSymbol
style: "short-dot",
width: 3.5,
color: "yellow"
}
});
}
return null;
}
// Get the last segment of the polyline that is being drawn
function getLastSegment(polyline) {
const line = polyline.clone();
const lastXYPoint = line.removePoint(0, line.paths[0].length - 1);
const existingLineFinalPoint = line.getPoint(
0,
line.paths[0].length - 1
);
return {
type: "polyline",
spatialReference: view.spatialReference,
hasZ: false,
paths: [
[
[existingLineFinalPoint.x, existingLineFinalPoint.y],
[lastXYPoint.x, lastXYPoint.y]
]
]
};
}
});
</script>
</head>
<body>
<!-- https://developers.arcgis.com/javascript/latest/esri-icon-font/ -->
<div id="viewDiv">
<div id="point-button" class="esri-widget esri-widget--button esri-interactive" title="Draw point">
<span class="esri-icon-map-pin"></span>
</div>
<div id="line-button" class="esri-widget esri-widget--button esri-interactive" title="Draw polyline">
<span class="esri-icon-polyline"></span>
</div>
<div id="polygon-button" class="esri-widget esri-widget--button esri-interactive" title="Draw polygon">
<span class="esri-icon-polygon"></span>
</div>
</div>
</body>
</html>