Is it possible to use the ArcGIS JS API to drag and drop a pin. The user would like to be able to see the pin as they move, I tried removing and re-adding the graphic layer, but I can't find any examples where the graphic marker symbol is visible to the user as they move it. I'm able to use the sketch view model, in the below example, but the marker disappears and is replaced with the default sketch symbol.
Thanks!
Test Graphics Layer
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Test Graphics Layer</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.9/esri/css/main.css">
<script src="https://js.arcgis.com/4.9/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Sketch/SketchViewModel",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/support/webMercatorUtils"
], function(
Map, MapView, SketchViewModel, Graphic, GraphicsLayer, webMercatorUtils
) {
let editGraphic;
// GraphicsLayer to hold graphics created via sketch view model
const graphicsLayer = new GraphicsLayer({
id: "tempGraphics"
});
const map = new Map({
basemap: "gray",
layers: [graphicsLayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
center: [-121.5, 38.555],
zoom: 11
});
var point = {
type: "point", // autocasts as new Point()
longitude: -121.5,
latitude: 38.555
};
var markerSymbol = {
type: "picture-marker", // autocasts as new PictureMarkerSymbol()
url: "https://daraobeirne.github.io/kisspng-drawing-pin-world-map-logo-push-vector-5ae029f6ddeaf4.198342921524640246909.png",
width: "30px",
height: "30px"
};
var pointGraphic = new Graphic({
geometry: webMercatorUtils.geographicToWebMercator(point),
symbol: markerSymbol
});
view.when(function () {
graphicsLayer.graphics.addMany([pointGraphic]);
// create a new sketch view model
const sketchViewModel = new SketchViewModel({
view,
layer: graphicsLayer,
updateOnGraphicClick: true
});
setUpClickHandler();
sketchViewModel.on("update-complete", updateGraphic);
sketchViewModel.on("update-cancel", updateGraphic);
function updateGraphic(event) {
var graphic = new Graphic({
geometry: event.geometry,
symbol: editGraphic.symbol
});
graphicsLayer.add(graphic);
editGraphic = null;
}
function setUpClickHandler() {
view.on("click", function (event) {
view.hitTest(event).then(function (response) {
var results = response.results;
if (results.length > 0) {
for (var i = 0; i < results.length; i++) {
// Check if we're already editing a graphic
if (!editGraphic && results[i].graphic.layer.id === "tempGraphics") {
// Save a reference to the graphic we intend to update
editGraphic = results[i].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
graphicsLayer.remove(editGraphic);
sketchViewModel.update(editGraphic);
break;
}
}
}
});
});
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
Solved! Go to Solution.
Dara,
If you move up to a newer release of the api then you can do this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Test Graphics Layer</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
<script src="https://js.arcgis.com/4.14/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Sketch/SketchViewModel",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/support/webMercatorUtils"
], function(
Map, MapView, SketchViewModel, Graphic, GraphicsLayer, webMercatorUtils
) {
let editGraphic;
// GraphicsLayer to hold graphics created via sketch view model
const graphicsLayer = new GraphicsLayer({
id: "tempGraphics"
});
const map = new Map({
basemap: "gray",
layers: [graphicsLayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
center: [-121.5, 38.555],
zoom: 11
});
var point = {
type: "point", // autocasts as new Point()
longitude: -121.5,
latitude: 38.555
};
var markerSymbol = {
type: "picture-marker", // autocasts as new PictureMarkerSymbol()
url: "https://daraobeirne.github.io/kisspng-drawing-pin-world-map-logo-push-vector-5ae029f6ddeaf4.198342921524640246909.png",
width: "30px",
height: "30px"
};
var pointGraphic = new Graphic({
geometry: webMercatorUtils.geographicToWebMercator(point),
symbol: markerSymbol
});
view.when(function () {
graphicsLayer.graphics.add(pointGraphic);
// create a new sketch view model
const sketchViewModel = new SketchViewModel({
view: view,
layer: graphicsLayer,
updateOnGraphicClick: true,
pointSymbol: markerSymbol
});
setUpClickHandler();
sketchViewModel.on("update-complete", updateGraphic);
sketchViewModel.on("update-cancel", updateGraphic);
sketchViewModel.on('update', function(evt){
evt.graphics[0].symbol = markerSymbol;
});
function updateGraphic(event) {
var graphic = new Graphic({
geometry: event.geometry,
symbol: editGraphic.symbol
});
graphicsLayer.add(graphic);
editGraphic = null;
}
function setUpClickHandler() {
view.on("click", function (event) {
view.hitTest(event).then(function (response) {
var results = response.results;
if (results.length > 0) {
for (var i = 0; i < results.length; i++) {
// Check if we're already editing a graphic
if (!editGraphic && results[i].graphic.layer.id === "tempGraphics") {
// Save a reference to the graphic we intend to update
editGraphic = results[i].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
graphicsLayer.remove(editGraphic);
sketchViewModel.update([editGraphic]);
break;
}
}
}
});
});
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
Dara,
If you move up to a newer release of the api then you can do this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Test Graphics Layer</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.14/esri/css/main.css">
<script src="https://js.arcgis.com/4.14/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Sketch/SketchViewModel",
"esri/Graphic",
"esri/layers/GraphicsLayer",
"esri/geometry/support/webMercatorUtils"
], function(
Map, MapView, SketchViewModel, Graphic, GraphicsLayer, webMercatorUtils
) {
let editGraphic;
// GraphicsLayer to hold graphics created via sketch view model
const graphicsLayer = new GraphicsLayer({
id: "tempGraphics"
});
const map = new Map({
basemap: "gray",
layers: [graphicsLayer]
});
const view = new MapView({
container: "viewDiv",
map: map,
center: [-121.5, 38.555],
zoom: 11
});
var point = {
type: "point", // autocasts as new Point()
longitude: -121.5,
latitude: 38.555
};
var markerSymbol = {
type: "picture-marker", // autocasts as new PictureMarkerSymbol()
url: "https://daraobeirne.github.io/kisspng-drawing-pin-world-map-logo-push-vector-5ae029f6ddeaf4.198342921524640246909.png",
width: "30px",
height: "30px"
};
var pointGraphic = new Graphic({
geometry: webMercatorUtils.geographicToWebMercator(point),
symbol: markerSymbol
});
view.when(function () {
graphicsLayer.graphics.add(pointGraphic);
// create a new sketch view model
const sketchViewModel = new SketchViewModel({
view: view,
layer: graphicsLayer,
updateOnGraphicClick: true,
pointSymbol: markerSymbol
});
setUpClickHandler();
sketchViewModel.on("update-complete", updateGraphic);
sketchViewModel.on("update-cancel", updateGraphic);
sketchViewModel.on('update', function(evt){
evt.graphics[0].symbol = markerSymbol;
});
function updateGraphic(event) {
var graphic = new Graphic({
geometry: event.geometry,
symbol: editGraphic.symbol
});
graphicsLayer.add(graphic);
editGraphic = null;
}
function setUpClickHandler() {
view.on("click", function (event) {
view.hitTest(event).then(function (response) {
var results = response.results;
if (results.length > 0) {
for (var i = 0; i < results.length; i++) {
// Check if we're already editing a graphic
if (!editGraphic && results[i].graphic.layer.id === "tempGraphics") {
// Save a reference to the graphic we intend to update
editGraphic = results[i].graphic;
// Remove the graphic from the GraphicsLayer
// Sketch will handle displaying the graphic while being updated
graphicsLayer.remove(editGraphic);
sketchViewModel.update([editGraphic]);
break;
}
}
}
});
});
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
Great!! Thank you very much Robert this is perfect!
Forgive my ignorance, as I a developer newly navigating the obscene complexities of ArcGIS JS, though can't that be simplified by just having an isDragging flag and updating the graphic's geometry directly?
Have you tested your code? Does it work?
Yes, it works.
I can confirm this works for me - this mimicks the Google Maps dragging behaviour nicely and without the need to use any ArcGIS widgets.
Yes, it does. I am new here, can anybody care to explain, why? The movement takes place out of the hitTest callback, so is there a downside or a problem with this approach? Anyway, thank you @CoMAGOL_ADMINISTRATOR