<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>Satellites in 3D view | 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>
<arcgis-scene basemap="satellite">
<arcgis-zoom slot="top-left"></arcgis-zoom>
<arcgis-navigation-toggle slot="top-left"></arcgis-navigation-toggle>
<arcgis-compass slot="top-left"> </arcgis-compass>
<script src="https://developers.arcgis.com/javascript/latest/assets/sample-code/satellites-3d/satellite.js"></script>
const [GraphicsLayer, Graphic, esriRequest, Popup, reactiveUtils] = await $arcgis.import([
"@arcgis/core/layers/GraphicsLayer.js",
"@arcgis/core/Graphic.js",
"@arcgis/core/request.js",
"@arcgis/core/widgets/Popup.js",
"@arcgis/core/core/reactiveUtils.js",
// Request the satellite data from hosted site
let url = "https://developers.arcgis.com/javascript/latest/assets/sample-code/satellites-3d/brightest.txt";
// Create GraphicsLayers for storing satellites and their tracks
const satelliteLayer = new GraphicsLayer();
const satelliteTracks = new GraphicsLayer();
}).then(function (response) {
const txt = response.data;
// Parse the satellite TLE data
const lines = txt.split("\n");
const count = (lines.length / 3).toFixed(0);
for (let i = 0; i < count; i++) {
let commonName = lines[i * 3 + 0];
let line1 = lines[i * 3 + 1];
let line2 = lines[i * 3 + 2];
/*************************************************
* Create attributes for the International
* designator and Norad identifier. See the
* https://www.space-track.org/documentation#/tle
*************************************************/
const designator = line1.substring(9, 16);
const launchYear = designator.substring(0, 2);
const fullLaunchYear = Number(launchYear) >= 57 ? `19${launchYear}` : `20${launchYear}`;
const launchNum = Number(designator.substring(2, 5)).toString();
const noradId = Number(line1.substring(3, 7));
satelliteLoc = getSatelliteLocation(new Date(time), line1, line2);
console.error("Getting satellite location: ", error);
if (satelliteLoc !== null) {
// autocasts as new PopupTemplate()
content: "Launch number {number} of {year}",
// Create a popup action to display the satellite track.
title: "Show Satellite Track",
className: "esri-icon-globe",
let graphic = new Graphic({
type: "picture-marker", // autocasts as new PictureMarkerSymbol()
url: "https://developers.arcgis.com/javascript/latest/assets/sample-code/satellites-3d/satellite.png",
satelliteLayer.add(graphic);
/*****************************************************************
* Get a reference to the Scene component and set it up
*****************************************************************/
const viewElement = document.querySelector("arcgis-scene");
viewElement.constraints = {
max: 12000000000, // meters
viewElement.popup = new Popup({
viewElement.environment = {
lighting: { type: "virtual" },
await viewElement.viewOnReady();
// Add satellite layers to the map
viewElement.map.addMany([satelliteLayer, satelliteTracks]);
() => viewElement.popup.selectedFeature,
satelliteTracks.removeAll();
viewElement.popup.on("trigger-action", (event) => {
if (event.action.id === "track") {
satelliteTracks.removeAll();
let graphic = viewElement.popup.selectedFeature;
for (let i = 0; i < 60 * 24; i++) {
loc = getSatelliteLocation(
new Date(graphic.attributes.time + i * 1000 * 60),
graphic.attributes.line1,
graphic.attributes.line2,
trackFeatures.push([loc.x, loc.y, loc.z]);
let track = new Graphic({
type: "polyline", // autocasts as new Polyline()
type: "line-3d", // autocasts as new LineSymbol3D()
type: "line", // autocasts as new LineSymbol3DLayer()
color: [192, 192, 192, 0.5],
satelliteTracks.add(track);
function getSatelliteLocation(date, line1, line2) {
/****************************************************
* satellite-js is a library that includes a set of
* functions to convert TLE to geographic locations
* We use this to get the geographic location of the
* satellites for the current date. For more details
* on satellite-js visib the github repo
* https://github.com/shashwatak/satellite-js
****************************************************/
const satrec = satellite.twoline2satrec(line1, line2);
const position_and_velocity = satellite.propagate(
const position_eci = position_and_velocity.position;
// Check for invalid position
typeof position_eci.x !== "number" ||
typeof position_eci.y !== "number" ||
typeof position_eci.z !== "number"
const gmst = satellite.gstime_from_date(
const position_gd = satellite.eci_to_geodetic(position_eci, gmst);
let longitude = position_gd.longitude;
let latitude = position_gd.latitude;
let height = position_gd.height;
if (isNaN(longitude) || isNaN(latitude) || isNaN(height)) {
const rad2deg = 180 / Math.PI;
while (longitude < -Math.PI) {
longitude += 2 * Math.PI;
while (longitude > Math.PI) {
longitude -= 2 * Math.PI;
type: "point", // Autocasts as new Point()