Hi, I need to update a graphic point, so that it always stays in front of the camera:
This is what I’m trying, but although the cameraX and cameraY are perfectly updating with the prober coordinates I can’t figure out how to clone the graphic with the new coordinates, so basically it needs to refresh the points XY with the new values, when I move the camera and then redraw the point. I’ve been searching for a long time for an answer, so I hope I can get some help
Solved! Go to Solution.
Kenneth,
OK, you are close but you need to add the point to the GL inside the stationary function as well.
var cameraX, cameraY, point, markerSymbol;
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
markerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [226, 119, 40],
size : 100,
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 0.2
}
};
watchUtils.whenTrue(view, "stationary", function() {
graphicsLayer.removeAll();
cameraX = view.camera.position.longitude;
cameraY = view.camera.position.latitude + 0.20;
point = {
type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY
};
graphicsLayer.add(new Graphic({
geometry: point,
symbol: markerSymbol,
}));
});
Kenneth,
You are using watchUtils stationary to get the camera x and y (not sure why you have those separate...) but you create your point outside of those functions so the point will never get updated with the correct xy.
var cameraX, cameraY, point;
watchUtils.whenTrue(view, "stationary", function() {
cameraX = view.camera.position.longitude;
cameraY = view.camera.position.latitude + 0.05;
point = {
type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY
};
});
Hi Robert thank you, sorry for the late reply on this. I can't seem to get this to work at all.
I would expect, that I also would need to update the graphic layer when I move the camera, so tride different variations of the watchUtils. So I guess the graphic don’t re-read the new camera/cameraY
Kenneth,
OK, you are close but you need to add the point to the GL inside the stationary function as well.
var cameraX, cameraY, point, markerSymbol;
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
markerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [226, 119, 40],
size : 100,
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 0.2
}
};
watchUtils.whenTrue(view, "stationary", function() {
graphicsLayer.removeAll();
cameraX = view.camera.position.longitude;
cameraY = view.camera.position.latitude + 0.20;
point = {
type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY
};
graphicsLayer.add(new Graphic({
geometry: point,
symbol: markerSymbol,
}));
});
We wrote on almost the same time, I was even closer 🙂
Now I got it, awesome thank you Robert.
Really happy now 🙂
Well, I’m not getting that far in my script as I expected. Maybe I should start a new thread, but since we are on our way here, I’ll continue and pass the result to https://community.esri.com/thread/226394-show-camera-position-relative-to-ground
The idea was to take everything in small stages, learn something on the way, but I face issues, every time I try to move forward
So I’m trying to combine the Query Elevation (points) https://developers.arcgis.com/javascript/latest/sample-code/elevation-query-points/index.html with the graphic created on camera movement, so I’m trying to use queryElevation() and been trying in many different ways. Now I’m just getting dizzy.
So what I would need at the end, is to extract the z value from the graphic, the use view.camera.position.z – the Graphic Z value, then I should have the camera elevation from ground, which will answer my show camera position relative to ground post.
In what I’m testing I’m using the ElevationLayer from the elevation query points. I can’t figure out if my issues are related to the graphic using WGS84 (wkid: 4326) and the layer are using wkid: 3857, or if the graphic will reproject to the elevation layer.
Thanks.
Kenneth,
I would have to see the code.
Thank you. This is the almost clean version, where I haven’t any queryElevation() stuff in there:
I’m trying to get this implemented, in some way, but yea, it fails:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Add Graphics to a SceneView - 4.11</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.11/esri/css/main.css">
<script src="https://js.arcgis.com/4.11/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#outputMessages {
position: absolute;
z-index: 70;
top: 0px;
right: 0;
bottom: 0;
box-sizing: border-box;
padding: 20px;
height: 100%;
width: 350px;
background: rgba(0, 0, 0, 0.7);
color: white;
font-size: 14px;
line-height: 30px;
overflow: auto;
}
#outputMessages span {
color: #f7be81;
font-weight: bold;
}
</style>
<script>
require([
"esri/Map",
"esri/views/SceneView",
"esri/Graphic",
"esri/geometry/Polyline",
"esri/geometry/Point",
"esri/layers/ElevationLayer",
"esri/core/promiseUtils",
"esri/core/watchUtils",
"esri/layers/GraphicsLayer",
], function (
Map,
SceneView,
Graphic,
Polyline,
Point,
ElevationLayer,
promiseUtils, watchUtils, GraphicsLayer
) {
// Create elevation layers
var beforeLandslideUrl =
"//elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer/";
var beforeLandslideLayer = new ElevationLayer({
url: beforeLandslideUrl
});
// Create Map and View
var map = new Map({
basemap: "satellite",
ground: {
layers: [beforeLandslideLayer]
}
});
var view = new SceneView({
container: "viewDiv",
map: map,
camera: {
// initial view:
heading: 332.8,
tilt: 65.5,
position: {
x: -13563643,
y: 6153016,
z: 577,
spatialReference: {
wkid: 3857
}
},
heading: 0.34445102566290225,
tilt: 82.95536300536367
}
});
var outputMessages = document.getElementById("outputMessages");
var cameraX, cameraY, point, markerSymbol, graZ;
var graphicsLayer = new GraphicsLayer();
map.add(graphicsLayer);
markerSymbol = {
type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
color: [226, 119, 40],
size: 100,
outline: { // autocasts as new SimpleLineSymbol()
color: [255, 255, 255],
width: 0.2
}
};
watchUtils.whenTrue(view, "stationary", function () {
graphicsLayer.removeAll();
cameraX = view.camera.position.longitude;
cameraY = view.camera.position.latitude + 0.2;
point = {
type: "point", // autocasts as new Point()
x: cameraX,
y: cameraY
};
beforeLandslideLayer.queryElevation(new Point(point), { returnSampleInfo: true })
.then(function (result) {;
graZ = result.geometry.z;
var info = "<span> the view center changed. </span>" +
"<br> x: " + cameraX +
"<br> y: " + cameraY +
"<br> z: " + graZ +
"<br> Camera z: " + (view.camera.position.z - graZ)
displayMessage(info);
})
// Failed to sample (e.g. service unavailable)
.catch(function (error) {
console.error("Failed to query elevation:", error);
});
graphicsLayer.add(new Graphic({
geometry: point,
symbol: markerSymbol,
}));
});
function displayMessage(info) {
outputMessages.innerHTML = info;
outputMessages.scrollTop = outputMessages.scrollHeight;
}
});
</script>
</head>
<body>
<div id="viewDiv">
<div id="outputMessages"></div>
<div id="titleDiv"></div>
</div>
</body>
</html>
That is so amazing, thank you so much. Exactly what I would need.