<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Sample 3D Draw Line/Measure Tool</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.4/esri/css/main.css">
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://js.arcgis.com/4.4/"></script>
</head>
<body>
<div>
<span id="lineButton" class="esri-widget-button esri-widget esri-interactive button">
<span class="esri-icon-polyline"></span>
</span>
</div>
<div>
<span id="eraseLineButton" class="esri-widget-button esri-widget esri-interactive button">
<span class="esri-icon-erase"></span>
</span>
</div>
<div>
<span id="clearButton" class="esri-widget-button esri-widget esri-interactive button">
<span class="esri-icon-trash"></span>
</span>
</div>
<div id="map"></div>
<div id="disclaimer">This returns a 2D measurement despite draping</div>
</body>
</html>
html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#lineButton {
top: 5px;
right: 5px
}
#eraseLineButton {
top: 45px;
right: 5px
}
#clearButton {
top: 85px;
right: 5px
}
#lineButton.esri-draw-button-selected {
opacity: 1;
background-color: rgba(173, 216, 230, 1);
color: white;
}
#lineButton.esri-draw-button-selected:hover {
background-color: rgba(173, 216, 230, 0.5);
color: white;
}
#disclaimer {
position: absolute;
bottom: 18px;
left: 2px;
font-size: 12px;
font-family: sans-serif;
background-color: whitesmoke;
padding: 2px;
}
.button {
position: absolute;
z-index: 999;
}
require([
"esri/Map",
"esri/views/SceneView",
"esri/Camera",
"esri/symbols/SimpleLineSymbol",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/Polyline",
"esri/geometry/Point",
"esri/geometry/geometryEngine",
"esri/symbols/TextSymbol"
], function(Map, SceneView, Camera, SimpleLineSymbol, Graphic,
GraphicsLayer, Polyline, Point, geometryEngine, TextSymbol) {
var map = new Map({
basemap: "hybrid",
ground: "world-elevation"
});
var view = new SceneView({
map: map,
container: "map",
camera: new Camera({
heading: -90,
tilt: 65,
position: {
latitude: 43.75,
longitude: -110.6,
z: 8000,
}
})
});
var lineConfig = {
lineSymbol: new SimpleLineSymbol({
color: "lightblue",
width: "2px",
style: "solid"
}),
activeLine: null,
isLineActive: false
};
var lineGraphicsLayer = new GraphicsLayer({
graphics: []
});
var lineTextGraphicsLayer = new GraphicsLayer({
graphics: []
});
var pointerDownListener, pointerMoveListener,
doubleClickListener;
var clearFunction = function () {
map.remove(lineGraphicsLayer);
map.remove(lineTextGraphicsLayer);
lineGraphicsLayer.graphics.removeAll();
lineTextGraphicsLayer.graphics.removeAll();
};
var eraseLineFunction = function () {
var lineGraphicsLayerLength = lineGraphicsLayer.graphics.length;
lineGraphicsLayer.graphics.remove(lineGraphicsLayer.graphics.items[lineGraphicsLayerLength - 1]);
var lineTextGraphicsLayerLength = lineTextGraphicsLayer.graphics.length;
lineTextGraphicsLayer.graphics.remove(lineTextGraphicsLayer.graphics.items[lineTextGraphicsLayerLength - 1]);
};
var lineButton = document.getElementById("lineButton");
view.then(function () {
var lineFunction = function () {
if (!lineConfig.isLineActive) {
activateLine();
} else {
deactivateLine();
clearLine();
}
};
$(lineButton).click(lineFunction);
$("#eraseLineButton").click(eraseLineFunction);
$("#clearButton").click(clearFunction);
view.on("click", function (evt) {
evt.stopPropagation();
});
});
function createPoint(event) {
return view.toMap(event);
}
function activateLine() {
lineConfig.isLineActive = true;
lineButton.classList.toggle("esri-draw-button-selected");
pointerDownListener = view.on("pointer-down", function (event) {
event.stopPropagation();
var point = createPoint(event);
addLineVertex(point);
});
pointerMoveListener = view.on("pointer-move", function (event) {
if (lineConfig.activeLine) {
event.stopPropagation();
var point = createPoint(event);
updateFinalLineVertex(point);
}
});
doubleClickListener = view.on("double-click", function (event) {
event.stopPropagation();
var searchArea = addLineVertex(event.mapPoint, true);
if (!searchArea) {
return null;
}
deactivateLine();
});
}
function deactivateLine() {
lineConfig.isLineActive = false;
lineButton.classList.toggle("esri-draw-button-selected");
pointerDownListener.remove();
pointerMoveListener.remove();
doubleClickListener.remove();
lineConfig.activeLine = null;
}
function addLineVertex(point, isFinal) {
var line = lineConfig.activeLine;
var pathLength;
var longitude = point.x;
var latitude = point.y;
if (!line) {
line = new Polyline({
paths:[
[]
],
spatialReference: {
wkid: 102100
}
});
line.insertPoint(0, 0, point);
} else {
pathLength = line.paths[0].length;
line.insertPoint(0, pathLength, point);
}
lineConfig.activeLine = line;
return redrawLine(line, isFinal);
}
function redrawLine(line, finished) {
var lineGeometry = line;
clearLine();
var lineGraphic = new Graphic({
geometry: lineGeometry,
symbol: lineConfig.lineSymbol
});
view.graphics.add(lineGraphic);
lineGraphic.geometry.hasZ = false;
if (finished) {
var feetLength = geometryEngine.geodesicLength(line, "feet");
var formatedfeetLength = Math.abs(feetLength).toLocaleString('en-US', {
maximumFractionDigits: 2
});
var lineTextSymbol = new TextSymbol({
color: "white",
haloColor: "black",
haloSize: "1px",
text: formatedfeetLength + ' Feet',
font: {
size: 10,
family: "Arial, sans-serif",
weight: "normal"
}
});
lineGraphicsLayer.graphics.add(lineGraphic);
map.add(lineGraphicsLayer);
var lineTextX = lineGraphic.geometry.extent.center.longitude;
var lineTextY = lineGraphic.geometry.extent.center.latitude;
var lineTextPoint = new Point ({
x: lineTextX,
y: lineTextY
});
var lineTextGraphic = new Graphic ({
geometry: lineTextPoint,
symbol: lineTextSymbol
});
lineTextGraphicsLayer.graphics.add(lineTextGraphic);
map.add(lineTextGraphicsLayer);
view.graphics.remove(lineTextGraphic);
view.graphics.remove(lineGraphic);
}
return lineGeometry;
}
function updateFinalLineVertex(point) {
var line = lineConfig.activeLine.clone();
var pathLength = line.paths[0].length;
line.insertPoint(0, pathLength, point);
redrawLine(line);
}
function clearLine() {
var lineGraphic = view.graphics.find(function (graphic) {
return graphic.geometry.type === "polyline";
});
if (lineGraphic) {
view.graphics.remove(lineGraphic);
}
}
});
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |