<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Geometry operator - geodesic buffers | Sample | ArcGIS Maps SDK for JavaScript</title>
<!-- Load the ArcGIS Maps SDK for JavaScript from CDN -->
<script type="module" src="https://js.arcgis.com/5.0/"></script>
--calcite-block-padding: 0px;
<arcgis-map zoom="3" center="0,60">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-scene zoom="3" center="0,60">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
<arcgis-compass slot="top-left"></arcgis-compass>
<calcite-panel slot="top-right">
<calcite-block expanded label="info">
Press <span class="strong">b key</span> to enable
<span id="mode" class="strong">buffering</span>. Then click or move the mouse to buffer.
const [Map, GraphicsLayer, Graphic, geodesicBufferOperator] = await $arcgis.import([
"@arcgis/core/layers/GraphicsLayer.js",
"@arcgis/core/Graphic.js",
"@arcgis/core/geometry/operators/geodesicBufferOperator.js",
// Symbol definition for polylines
type: "simple-fill", // autocasts as new SimpleFillSymbol()
color: [255, 255, 0, 0.6],
// Symbol definition for points
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
// Indicates whether buffering is enabled
let bufferEnabled = false;
// Create a map to be shared by two views
// Add two graphics layers to the map, one for points, another for buffers
const bufferLayer = new GraphicsLayer();
const pointLayer = new GraphicsLayer();
map.addMany([bufferLayer, pointLayer]);
// Get the reference to the Map and Scene components
const viewElementMap = document.querySelector("arcgis-map");
const viewElementScene = document.querySelector("arcgis-scene");
// Assign the same map to both components
viewElementMap.map = map;
viewElementScene.map = map;
// Wait for the views to load
await viewElementMap.viewOnReady();
await viewElementScene.viewOnReady();
// Load the operator's dependencies and add event listeners
await geodesicBufferOperator.load();
viewElementMap.addEventListener("arcgisViewPointerMove", (event) => {
createBuffer(event.detail, viewElementMap.view);
viewElementScene.addEventListener("arcgisViewPointerMove", (event) => {
createBuffer(event.detail, viewElementScene.view);
viewElementMap.addEventListener("arcgisViewKeyDown", (event) => {
keyDownListener(event.detail);
viewElementScene.addEventListener("arcgisViewKeyDown", (event) => {
keyDownListener(event.detail);
console.log("geodesicBufferOperator dependencies and event listeners loaded.");
// ***** HELPER FUNCTIONS ***** //
* Stops propagation on the given event and constructs a point for
* @param {Object} event - Event object containing XY screen coordinates.
* @param {MapView | SceneView} view - View instance from which the point was obtained.
const createBuffer = (event, view) => {
// prevent further propagation of the current event bubbling up the event chain.
// in this case, it will prevent default `drag` event behavior for the MapView
// which is to move around the view by dragging the pointer.
// convert screen coordinates to map coordinates
const point = view.toMap(event);
* Buffers the given point by 500 kilometers.
* @param {esri/geometry/Point} point - A point instance to buffer.
const bufferPoint = (point) => {
// removes z-values from the point when taken from a SceneView.
// geometry operators do not support 3D geometries.
if (pointLayer.graphics.length === 0) {
const graphic = pointLayer.graphics.getItemAt(0);
graphic.geometry = point;
const buffer = geodesicBufferOperator.execute(point, 500, { unit: "kilometers" });
if (bufferLayer.graphics.length === 0) {
const graphic = bufferLayer.graphics.getItemAt(0);
graphic.geometry = buffer;
* When the b key is tapped, then buffering is enabled.
* @param {Object} event - The event object associated with the
function keyDownListener(event) {
const keyInput = event.key;
bufferEnabled = keyInput === "b" && !bufferEnabled;
document.getElementById("mode").textContent = bufferEnabled ? "navigation" : "buffering";