Demo2 draw-line
<!DOCTYPE html>
<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.22</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.22/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.22/"></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");
const draw = new Draw({
view: view
});
// 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"
],
updateVertices
);
};
// Checks if the last vertex is making the line intersect itself.
function updateVertices(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphic(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 createGraphic(event) {
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphic = 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(graphic.geometry);
// Add a new graphic for the intersecting segment.
if (intersectingSegment) {
view.graphics.addMany([graphic, intersectingSegment]);
}
// Just add the graphic representing the polyline if no intersection
else {
view.graphics.add(graphic);
}
// 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>
<div id="viewDiv">
<div id="line-button" class="esri-widget esri-widget--button
esri-interactive" title="Draw polyline">
<span class="esri-icon-polyline"></span>
</div>
</div>
</body>
</html>
效果预览图
分析
const draw = new Draw({
view: view
});
构造一个Draw实例
// 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"
],
updateVertices
);
};
// Checks if the last vertex is making the line intersect itself.
function updateVertices(event) {
// create a polyline from returned vertices
if (event.vertices.length > 1) {
const result = createGraphic(event);
// if the last vertex is making the line intersects itself,
// prevent the events from firing
if (result.selfIntersects) {
event.preventDefault();
}
}
}
官网例子:
// create a new instance of draw
let draw = new Draw({
view: view
});
// create an instance of draw polyline action
// the polyline vertices will be only added when
// the pointer is clicked on the view
let action = draw.create("polyline", {mode: "click"});
// fires when a vertex is added
action.on("vertex-add", function (evt) {
measureLine(evt.vertices);
});
// fires when the pointer moves
action.on("cursor-update", function (evt) {
measureLine(evt.vertices);
});
// fires when the drawing is completed
action.on("draw-complete", function (evt) {
measureLine(evt.vertices);
});
// fires when a vertex is removed
action.on("vertex-remove", function (evt) {
measureLine(evt.vertices);
});
function measureLine(vertices) {
view.graphics.removeAll();
let line = createLine(vertices);
let lineLength = geometryEngine.geodesicLength(line, "miles");
let graphic = createGraphic(line);
view.graphics.add(graphic);
}
function createLine(vertices) {
let polyline = {
type: "polyline", // autocasts as new Polyline()
paths: vertices,
spatialReference: view.spatialReference
}
return polyline;
}
相关API解释见此链接:developers.arcgis.com/javascript/…
结合官网解释和示例代码,这段sourcecode表示,action实例监听了vertex-add、cursor-update、draw-complete、vertex-remove、redo和undo行为,并执行updateVertices方法 将代码改为
// creates and returns an instance of PolyLineDrawAction
const action = draw.create("polygon", { mode: "hybrid" });
效果如下,既能点击又能拖拽:
// create a new graphic presenting the polyline that is being drawn on the view
function createGraphic(event) {
debugger;
const vertices = event.vertices;
view.graphics.removeAll();
// a graphic representing the polyline that is being drawn
const graphic = 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",
},
});
针对这段代码,阅读了官网上Graphics的教程: developers.arcgis.com/javascript/…