Public
Edited
Apr 26, 2023
Importers
Insert cell
Insert cell
Insert cell
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: [-122.27, 37.8],
padding: {
top: 16,
right: 16,
left: 16,
bottom: 16
},
zoom: 13,
container,
navigation: {
mouseWheelZoomEnabled: false,
browserTouchPanEnabled: false
}
});

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
});
mapView.graphics.add(polylineGraphic);

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

const handlerSamples = ArcGIS.reactiveUtils.watch(
() => elevationProfile.profiles.items?.[0]?.samples,
(samples) => {
mutable elevationSampleData = samples;
}
);

const handlerEffectiveUnits = ArcGIS.reactiveUtils.watch(
() => elevationProfile.effectiveUnits,
(value) => {
mutable elevationEffectiveUnits = value;
}
);

invalidation.then(() => {
mapView.destroy();
polylineGraphic.destroy();
elevationProfile.destroy();
handlerStats.remove();
handlerSamples.remove();
});
}
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",
{ maximumSignificantDigits: 3 }
)}</li>`
)}</ul>`;
}
Insert cell
renderElevationEffectiveUnits = (unitsObj) => {
return htl.html`<small>Distance is shown in <strong>${unitsObj?.distance}</strong> and elevation is shown in <strong>${unitsObj?.elevation}.</strong></small>`;
}
Insert cell
// Note: there are some duplicate values in the elevationSampleData produced by the ElevationProfileViewModel.
// We remove these to prevent rendering artifacts in the elevation chart
chartData = {
if (!dataReady) return;
let seen = new Set();
return elevationSampleData.filter((d) => {
return seen.has(d.distance) ? false : (seen.add(d.distance), true);
});
}
Insert cell
dataReady = Boolean(elevationSampleData) &&
Boolean(elevationViewModelStatistics)
Insert cell
isValidNumber = (d) => typeof d === "number" && !isNaN(d)
Insert cell
mutable elevationSampleData = null
Insert cell
mutable elevationViewModelStatistics = null
Insert cell
mutable elevationEffectiveUnits = 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
import { AreaChart } from "@d3/area-chart"
Insert cell
toGeoJson = require("@tmcw/togeojson")
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