I have some code below that i am using to allow the user to create a point line or polygon
Each click of the toolbox to chose between each geometry type clears the graphic layer.
What I want to do is:
After the geometry is drawn
Thoughts on the easiest way to do this?
Snip from a JSFiddle I was testing in:
<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;
}
.topcorner{
position:absolute;
top:0;
right:0;
width: 185px;
border: 1px solid black;
text-align: center;
}
.topcorner2{
position:absolute;
bottom:0;
right:0;
width: 185px;
border: 1px solid black;
text-align: center;
}
</style>
<script>
require([
"esri/Map","esri/views/MapView","esri/views/draw/Draw","esri/Graphic","esri/geometry/geometryEngine","esri/geometry/support/webMercatorUtils",
"dojo/dom",
"dojo/domReady!"
], (Map, MapView, Draw, Graphic, geometryEngine, webMercatorUtils, dom) => {
var geometryType = "nothing"
const map = new Map({
basemap: "gray-vector"
});
const view = new MapView({
container: "viewDiv",map: map,
zoom: 10,
center: [-77.367, 37.55]
});
// add the button for the draw tool
view.ui.add("clear-button", "top-left");
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("clear-button").onclick = () => {
view.graphics.removeAll();
geometryType = "nothing";
document.getElementById("info2").textContent=geometryType;
};
document.getElementById("point-button").onclick = () => {
view.graphics.removeAll();
geometryType = "point";
document.getElementById("info2").textContent=geometryType;
// 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();
geometryType = "polygon";
document.getElementById("info2").textContent=geometryType;
// 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
);
};
document.getElementById("line-button").onclick = () => {
view.graphics.removeAll();
geometryType = "line";
document.getElementById("info2").textContent=geometryType;
// 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
);
};
// https://developers.arcgis.com/javascript/latest/esri-icon-font/
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: "circle",
color: [51, 102, 153, 0.8],
size: "16px",
outline: { // autocasts as SimpleLineSymbol
color: [0, 0, 0],
width: 1
}
}
});
view.graphics.add(graphic);
}
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: [51, 102, 153, 0.8],
outline: {
color: [255, 255, 255],
width: 1
}
}
});
view.graphics.add(graphicPoly);
}
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: [45, 55, 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: 1,
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]
]
]
};
}
function showCoordinates(evt) {
var point = view.toMap({x: evt.x, y: evt.y});
//the map is in web mercator but display coordinates in geographic (lat, long)
var mp = webMercatorUtils.webMercatorToGeographic(point);
//display mouse coordinates
dom.byId("info").innerHTML = mp.x.toFixed(6) + ", " + mp.y.toFixed(6);
}
view.when(function(){
//after map loads, connect to listen to mouse move & drag events
view.on("pointer-move", showCoordinates);
});
});
</script>
</head>
<body>
<!-- https://developers.arcgis.com/javascript/latest/esri-icon-font/ -->
<div id="viewDiv">
<div id="clear-button" class="esri-widget esri-widget--button esri-interactive" title="Clear Grpahics">
<span class="esri-icon-erase"></span>
</div>
<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 class="topcorner">
<span id="info" ></span>
</div>
<div class="topcorner2">
<div id="info2">fghfghf</div>
</div>
</div>
</body>
</html>
Solved! Go to Solution.
Sorry that code was 3.x.
For 4.x it is
let buffGeom = bufferGralayer.graphics.items[0].geometry;
That was it.... implemented perfectly.... Thanks @RobertScheitlin__GISP
Here are my updates to your code UI wise has a bunch of updates to how things are styled and placed. Functionally the point method was not rendering the proper buffer visualization on the screen due to the improper symbol style being used and because the map is in webmercator the geometryEngine method should be geodesicBuffer and not buffer (my mistake there).
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1, maximum-scale=1,user-scalable=no"
/>
<title>Buffer Geometry</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 {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
.flex-container {
height: 100%;
display: flex;
overflow: hidden;
}
#viewDiv {
flex: 2;
padding: 0;
margin: 0;
}
.side-panel {
padding: 1em;
overflow: auto;
}
.FixedHeightContainer {
float: left;
height: 380px;
width: 230px;
padding: 3px;
background: rgb(112, 128, 144, 0.5);
}
#info {
min-height: 17px;
}
.header {
height: 30px;
padding-top: 5px;
}
.geometryResultsdiv {
height: 345px;
overflow: auto;
background: #fff;
font-size: 8px;
}
.menu {
display: table;
width: 100%;
border: 1px solid black;
border-right: none;
box-sizing: border-box;
}
.menu>div {
display: table-row;
background-color: white;
}
.menu>div>div {
border-right: 1px solid black;
display: table-cell;
text-align: center;
vertical-align: middle;
}
@media screen and (max-width: 240px) {
.menu {
display: block;
float: left;
width: auto;
border: none;
}
.menu>div {
display: block;
}
.menu>div>div {
border: none;
padding-right: 10px;
display: block;
text-align: left;
}
}
.boxpadding {
margin: 8px 0;
}
.float-container {
display: flex;
padding: 2px;
gap: 8px;
margin: 8px 0;
}
.float-child1 {
flex: 1;
}
.float-child2 {
flex: 2;
}
</style>
<script>
function valDistance() {
d = document.getElementById("distance").value;
document.getElementById("infoDistance").textContent = "Distance: " + d;
}
function valType() {
t = document.getElementById("distanceType").value;
document.getElementById("infoType").textContent = "Type: " + t;
}
require([
"esri/Map", "esri/views/MapView", "esri/views/draw/Draw", "esri/Graphic", "esri/geometry/geometryEngine",
"esri/geometry/support/webMercatorUtils",
"esri/layers/GraphicsLayer"
], (Map, MapView, Draw, Graphic, geometryEngine, webMercatorUtils, GraphicsLayer) => {
var geometryType = "No Geometry Selected"
let bufferGralayer = new GraphicsLayer({
id: "BufferGraLyr",
});
bufferGralayer.opacity = 0.5;
const map = new Map({
basemap: "gray-vector",
layers: [bufferGralayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 10,
center: [-77.367, 37.55]
});
const draw = new Draw({
view: view
});
// THIS IS FOR THE BUTTONS IN THE SIDE BAR
document.getElementById("clear-button2").onclick = () => {
view.graphics.removeAll();
bufferGralayer.removeAll();
geometryType = "No Geometry Selected";
document.getElementById("info2").textContent = geometryType;
document.getElementById("geometryResultsdiv").textContent = "";
};
document.getElementById("point-button2").onclick = () => {
view.graphics.removeAll();
bufferGralayer.removeAll();
document.getElementById("geometryResultsdiv").innerText = "";
geometryType = "point";
document.getElementById("info2").textContent = "Geometry: " + geometryType;
const action = draw.create("point");
view.focus();
action.on("cursor-update", function (evt) {
updateVerticesPoint(evt.coordinates);
});
action.on("draw-complete", function (evt) {
updateVerticesPoint(evt.coordinates);
setTimeout(() => {
document.getElementById("geometryResultsdiv").innerText = JSON.stringify(bufferGralayer.graphics.items[0].geometry);
}, 200);
});
};
document.getElementById("polygon-button2").onclick = () => {
view.graphics.removeAll();
bufferGralayer.removeAll();
document.getElementById("geometryResultsdiv").innerText = "";
geometryType = "polygon";
document.getElementById("info2").textContent = "Geometry: " + geometryType;
const action = draw.create("polygon");
view.focus();
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesPolygon
);
};
document.getElementById("line-button2").onclick = () => {
view.graphics.removeAll();
bufferGralayer.removeAll();
document.getElementById("geometryResultsdiv").innerText = "";
geometryType = "line";
document.getElementById("info2").textContent = "Geometry: " + geometryType;
const action = draw.create("polyline");
view.focus();
action.on(
[
"vertex-add",
"vertex-remove",
"cursor-update",
"redo",
"undo",
"draw-complete"
],
updateVerticesLine
);
};
function updateVerticesPoint(coordinates) {
//// create a polyline from returned vertices
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: "circle",
size: "16px",
color: [70, 90, 141, 0.4],
outline: {
color: [47, 76, 119, 0.5],
width: 1
}
}
});
view.graphics.add(graphic);
BufferGeom(graphic.geometry);
}
function updateVerticesPolygon(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphicPolygon(event);
}
if(event.type === 'draw-complete'){
setTimeout(() => {
document.getElementById("geometryResultsdiv").innerText = JSON.stringify(bufferGralayer.graphics.items[0].geometry);
}, 200);
}
}
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();
}
}
if(event.type === 'draw-complete'){
setTimeout(() => {
document.getElementById("geometryResultsdiv").innerText = JSON.stringify(bufferGralayer.graphics.items[0].geometry);
}, 200);
}
}
function createGraphicPoint(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphicPnt = new Graphic({
geometry: {
type: "point",
spatialReference: view.spatialReference
},
symbol: {
type: "simple-marker", // autocasts as new SimpleFillSymbol
color: [255, 255, 255, 0.9], //[70,90,141,0.2],
opacity: 0.2,
outline: {
color: [255, 255, 255, 0.9], //[47,76,119, 0.2],
width: 1
}
}
});
view.graphics.add(graphicPnt);
BufferGeom(graphicPnt.geometry, 500);
}
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: [70, 90, 141, 0.4],
outline: {
color: [47, 76, 119],
width: 1
}
}
});
view.graphics.add(graphicPoly);
BufferGeom(graphicPoly.geometry);
}
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: [70, 90, 141, 0.4],
width: 1,
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);
BufferGeom(graphicLine.geometry);
}
// return intersectingSegment
return {
selfIntersects: intersectingSegment
};
}
function BufferGeom(geom) {
var d = parseInt(document.getElementById("distance").value);
var t = document.getElementById("distanceType").value;
const buffGeom = geometryEngine.geodesicBuffer(geom, d, t);
const buffgra = new Graphic({
geometry: buffGeom,
symbol: {
type: "simple-fill", // autocasts as new SimpleFillSymbol
color: [112, 128, 144],
width: 1,
cap: "round",
join: "round"
}
});
bufferGralayer.removeAll();
bufferGralayer.add(buffgra);
// document.getElementById("geometryResultsdiv").innerText = JSON.stringify(userDefinedGeometry);
}
// 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]
]
]
};
}
function showCoordinates(evt) {
var point = view.toMap({
x: evt.x,
y: evt.y
});
//the map is in web mercator but display coordinates in geographic (lat, long)
var mp = webMercatorUtils.webMercatorToGeographic(point);
//display mouse coordinates
document.getElementById("info").innerHTML = mp.x.toFixed(6) + ", " + mp.y.toFixed(6);
}
view.when().then(() => {
//after map loads, connect to listen to mouse move & drag events
view.on("pointer-move", showCoordinates);
});
});
</script>
</head>
<body>
<div class="flex-container">
<div id="viewDiv"></div>
<div class="esri-widget side-panel">
<div>
<h2>Geometry Selection</h2>
<span id="info"></span>
<div class="float-container">
<div class="float-child1">
<div>Distance</div>
</div>
<div class="float-child2">
<select name="distance" id="distance" onchange="valDistance()" style="width:75px;">
<option value="1"> 1</option>
<option value="2"> 2</option>
<option value="3"> 3</option>
<option value="5"> 5</option>
<option value="10"> 10</option>
</select>
</div>
</div>
<div class="float-container">
<div class="float-child1">
<div>Unit</div>
</div>
<div class="float-child2">
<select name="distanceType" id="distanceType" onchange="valType()" style="width:75px;">
<option value="miles">mile(s)</option>
<option value="feet">feet</option>
<option value="meters">meter(s)</option>
</select>
</div>
</div>
<div class="boxpadding" id="infoDistance">Distance: 1</div>
<div class="boxpadding" id="infoType">Unit: mile</div>
<div class="menu">
<div>
<div id="clear-button2" class="esri-widget esri-widget--button esri-interactive" title="Clear Grpahics">
<span class="esri-icon-erase"></span>
</div>
<div id="point-button2" class="esri-widget esri-widget--button esri-interactive" title="Draw point">
<span class="esri-icon-map-pin"></span>
</div>
<div id="line-button2" class="esri-widget esri-widget--button esri-interactive" title="Draw polyline">
<span class="esri-icon-polyline"></span>
</div>
<div id="polygon-button2" class="esri-widget esri-widget--button esri-interactive" title="Draw polygon">
<span class="esri-icon-polygon"></span>
</div>
</div>
</div>
<div id="info2" class="boxpadding">Geometry:</div>
<div class="FixedHeightContainer">
<div class="header" id="header">Results</div>
<div class="geometryResultsdiv" id="geometryResultsdiv"> </div>
</div>
</div>
</div>
</div>
</body>
</html>
Cheers and thanks for your input.... learn more and more every day....