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
- Buffer the graphic and write that geometry to another graphic and display it in the map.
- I will then need to query for the new graphics geometry and pass this to another function for processing
- I have a DIV that has the current text for the graphic but I figured it might be better to query the graphic and determine the geometry type?
- Do I need to select the single graphic in the graphic layer?
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>