Public
Edited
Apr 17, 2023
1 star
Insert cell
Insert cell
Insert cell
map = {
const container = html`<div id="viewDiv" />
<style>
#viewDiv {
height: 600px;
width: ${width}px;
}
</style>
`;

yield container;

const map = new ArcGIS.Map({
basemap: "arcgis-topographic",
ground: "world-elevation"
});

const geojsonRenderer = new ArcGIS.SimpleRenderer({
symbol: new ArcGIS.SimpleLineSymbol({
width: 0,
color: "#fb12ff"
})
});

const geojsonLayer = new ArcGIS.GeoJSONLayer({
url: dataUrl,
renderer: geojsonRenderer
});

// add the geojson layer to the map
// this allows us to center the map on route's extent
map.add(geojsonLayer);

const mapView = new ArcGIS.MapView({
map,
center: [-122.27, 37.8],
padding: {
top: 16,
right: 16,
left: 16,
bottom: 16
},
zoom: 13,
container,
navigation: {
mouseWheelZoomEnabled: false,
browserTouchPanEnabled: false
}
});

const polyline = new ArcGIS.Polyline({
paths: coordinates
});

const polylineSymbol = {
type: "simple-line", // autocasts as SimpleLineSymbol()
color: [226, 119, 40], // rgb
width: 2.5
};

// the polylineGraphic is required for the ElevationProfile.input,
// we can't just use our GeoJSONLayer above.
const polylineGraphic = new ArcGIS.Graphic({
geometry: polyline,
symbol: polylineSymbol
});
mapView.graphics.add(polylineGraphic);
console.log(polylineGraphic);

// add the elevation profile
const elevationProfile = new ArcGIS.ElevationProfile({
view: mapView,
input: polylineGraphic,
unit: "imperial",
profiles: [
/** autocasts as new ElevationProfileLineGround()
uses the map's ground layer to compute elevation instead of the GeoJSON/Graphic's Z values
*/
{
type: "ground",
color: "#61d4a4",
title: "Ground elevation"
},

/** autocasts as new ElevationProfileLineInput()
uses the GeoJSON/Graphic's Z values for computing the elevation
*/
{
type: "input",
color: "#f57e42",
title: "Line elevation"
}
]
});

// set the map's zoom and extent to that of the geojson layer's
geojsonLayer
.when(() => {
return geojsonLayer.queryExtent();
})
.then((response) => {
mapView.goTo(response.extent);
});

// add the elevation profile widget to the map view
mapView.ui.add(elevationProfile, "bottom-left");

// listen for changes to the elevationProfile's profile property
// and access the first profile's statistics
const handler = ArcGIS.reactiveUtils.watch(
() => elevationProfile.profiles.items?.[0]?.statistics,
(stastics) => {
mutable elevationStatistics = stastics;
}
);

// do clean up when this cell re-runs
invalidation.then(() => {
mapView.destroy();
polylineGraphic.destroy();
elevationProfile.destroy();
handler.remove();
});
}
Insert cell
Insert cell
Insert cell
map2 = {
const container = html`<div id="viewDiv" />
<style>
#viewDiv {
height: 600px;
width: ${width}px;
}
</style>
`;

yield container;

const map = new ArcGIS.Map({
basemap: "arcgis-topographic",
ground: "world-elevation"
});

const mapView = new ArcGIS.MapView({
map,
center: [0, 0], //[-122.27, 37.8],
padding: {
top: 16,
right: 16,
left: 16,
bottom: 16
},
zoom: 13,
container,
navigation: {
mouseWheelZoomEnabled: false,
browserTouchPanEnabled: false
}
});

/* NOTE: that instead of relying on a GeoJSONLayer's extent to set the Map's center and zoom,
we can use a Graphic's geometry and avoid having to create a GeoJSONLayer all together. */

// const geojsonRenderer = new ArcGIS.SimpleRenderer({
// symbol: new ArcGIS.SimpleLineSymbol({
// width: 0,
// color: "#fb12ff"
// })
// });

// const geojsonLayer = new ArcGIS.GeoJSONLayer({
// url: dataUrl,
// renderer: geojsonRenderer
// });
// map.add(geojsonLayer);
// geojsonLayer
// .when(() => {
// return geojsonLayer.queryExtent();
// })
// .then((response) => {
// mapView.goTo(response.extent);
// });

const polyline = new ArcGIS.Polyline({
paths: coordinates
});

const polylineSymbol = {
type: "simple-line", // autocasts as SimpleLineSymbol()
color: [226, 119, 40],
width: 2.5
};

const polylineGraphic = new ArcGIS.Graphic({
geometry: polyline,
symbol: polylineSymbol
});

// will be above other graphics in the map.
// alternatively create a graphics layer and add to the map view.
mapView.graphics.add(polylineGraphic);

// zoom to the graphic's geometry extent
mapView.goTo(polylineGraphic.geometry);

const elevationProfile = new ArcGIS.ElevationProfileViewModel({
view: mapView,
input: polylineGraphic,
unit: "imperial",
profiles: [
{
type: "input",
color: "#f57e42",
title: "Line elevation"
}
]
});
const handler = ArcGIS.reactiveUtils.watch(
() => elevationProfile.profiles.items?.[0]?.statistics,
(statistics) => {
mutable elevationViewModelStatistics = statistics;
}
);

invalidation.then(() => {
mapView.destroy();
polylineGraphic.destroy();
elevationProfile.destroy();
handler.remove();
});
}
Insert cell
mutable debug = null
Insert cell
Insert cell
renderElevationStats = (statsObj) => {
return htl.html`<h3>Elevation Statistics (imperial units)</h3><ul style="padding: 0">${Object.entries(
statsObj
).map(
([key, value]) =>
htl.html`<li style="margin: 0 0.5em 0 0; display: inline-block;"><strong>${key}</strong>: ${value.toLocaleString(
"en-US",
{ maximumFractionDigits: 0 }
)}</li>`
)}</ul>`;
}
Insert cell
mutable elevationViewModelStatistics = null
Insert cell
mutable elevationStatistics = null
Insert cell
dataUrl = {
const blob = new Blob([JSON.stringify(data)], { type: "application/json" });
const url = URL.createObjectURL(blob);
return url;
}
Insert cell
coordinates = data.features[0].geometry.coordinates
Insert cell
data = toGeoJson.gpx(dataRaw)
Insert cell
dataRaw = FileAttachment("Luckyduck_Shop_Ride__168__Goldenrod_(copy).gpx").xml()
Insert cell
Insert cell
JS_API_VERSION = 4.25
Insert cell
JS_API_BASE_URL = `https://js.arcgis.com/${JS_API_VERSION}/@arcgis/core`
Insert cell
// NOTE: This key will only work for this notebook, please acquire your own at: https://developers.arcgis.com/api-keys
JS_API_KEY = "AAPKeaa067e241884f1f8ea72a5593cb8821aRuJV_aPxvhDXViKpdrzEOnB8RKhvKVPogv2Ry0d5AlAMEqq8S66zKkwHWHFBZKg"
Insert cell
getImport = async (path, ext = ".js") =>
await (
await import(`${JS_API_BASE_URL}${path}${ext}`)
).default
Insert cell
ArcGIS = {
const imports = await Promise.all(
[
"/config",
"/layers/GeoJSONLayer",
"/Map",
"/views/MapView",
"/renderers/SimpleRenderer",
"/symbols/SimpleLineSymbol",
"/widgets/ElevationProfile",
"/widgets/ElevationProfile/ElevationProfileViewModel",
"/geometry/Polyline",
"/Graphic"
].map((d) => getImport(d))
);

const importNames = [
"Config",
"GeoJSONLayer",
"Map",
"MapView",
"SimpleRenderer",
"SimpleLineSymbol",
"ElevationProfile",
"ElevationProfileViewModel",
"Polyline",
"Graphic"
];

const ArcGIS = Object.fromEntries(imports.map((d, i) => [importNames[i], d]));
const reactiveUtils = await import(
`${JS_API_BASE_URL}/core/reactiveUtils.js`
);
ArcGIS.reactiveUtils = reactiveUtils;

const { Config } = ArcGIS;
Config.apiKey = JS_API_KEY;

if (!Config._style) {
const href = await require.resolve(
`${JS_API_BASE_URL}/assets/esri/themes/light/main.css`
);
document.head.appendChild(
(Config._style = html`<link href=${href} rel=stylesheet>`)
);
}

return ArcGIS;
}
Insert cell
toGeoJson = require("@tmcw/togeojson")
Insert cell
sampleXmlDocString = `<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Oregon 400t" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
<metadata>
<link href="http://www.garmin.com">
<text>Garmin International</text>
</link>
<time>2009-10-17T22:58:43Z</time>
</metadata>
<trk>
<name>Example GPX Document</name>
<trkseg>
<trkpt lat="47.644548" lon="-122.326897">
<ele>4.46</ele>
<time>2009-10-17T18:37:26Z</time>
</trkpt>
<trkpt lat="47.644548" lon="-122.326897">
<ele>4.94</ele>
<time>2009-10-17T18:37:31Z</time>
</trkpt>
<trkpt lat="47.644548" lon="-122.326897">
<ele>6.87</ele>
<time>2009-10-17T18:37:34Z</time>
</trkpt>
</trkseg>
</trk>
</gpx>`;
Insert cell
{
const parser = new DOMParser();
const doc = parser.parseFromString("", "application/xml");
return toGeoJson.gpx(doc);
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more