Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a hillshade layer #1157

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions src/americana.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "maplibre-gl/dist/maplibre-gl.css";
import * as search from "./search.js";

import LegendControl from "./js/legend_control.js";
import { HillshadeControl } from "./js/icon_control.js";
import * as LegendConfig from "./js/legend_config.js";
import SampleControl from "openmapsamples-maplibre/OpenMapSamplesControl.js";
import { default as OpenMapTilesSamples } from "openmapsamples/samples/OpenMapTiles/index.js";
Expand Down Expand Up @@ -68,6 +69,7 @@ function shieldDefLoad(shields) {

map.addControl(new search.PhotonSearchControl(), "top-left");
map.addControl(new maplibregl.NavigationControl(), "top-left");
map.addControl(new HillshadeControl({ layerId: "hillshading" }), "top-left");

window.addEventListener("languagechange", (event) => {
console.log(`Changed to ${navigator.languages}`);
Expand Down
43 changes: 43 additions & 0 deletions src/js/icon_control.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export class HillshadeControl {
constructor({ layerId }) {
this._layerId = layerId;
}

_onClick = () => {
if (this._map.getLayoutProperty(this._layerId, "visibility") == "none") {
Copy link
Member

@1ec5 1ec5 Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Astonishingly, my iPhone 8 is able to keep up with the map with the hillshading enabled, but it turns the battery meter into a sad trombone. Should we hide the layer by default on mobile devices, or somehow detect less powerful devices?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I upgraded maplibre-gl, the changelog mentions some performance improvements, want to try again?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first render is reasonably quick, but there’s a lot more stuttering while panning than on main. The battery goes down by a few percent after about 20 seconds of panning around the Appalachians at zoom level 8. That’s still much better than the majority of ad-laden news websites these days, but the stuttering is a bummer.

this._map.setLayoutProperty(this._layerId, "visibility", "visible");
this._button.classList.add("maplibregl-ctrl-terrain-enabled");
this._button.title = "Disable terrain";
} else {
this._map.setLayoutProperty(this._layerId, "visibility", "none");
this._button.classList.remove("maplibregl-ctrl-terrain-enabled");
this._button.title = "Enable terrain";
}
};

onAdd(map) {
this._map = map;

this._container = document.createElement("div");
this._container.className = "maplibregl-ctrl maplibregl-ctrl-group";

this._button = document.createElement("button");
this._button.className = "maplibregl-ctrl-terrain";
this._button.classList.add("maplibregl-ctrl-terrain-enabled");
this._button.title = "Disable terrain";
this._button.addEventListener("click", this._onClick);
this._container.append(this._button);

const span = document.createElement("span");
span.className = "maplibregl-ctrl-icon";
span.setAttribute("aria-hidden", "true");
this._button.append(span);

return this._container;
}

onRemove() {
this._container.remove();
this._map = undefined;
}
}
12 changes: 12 additions & 0 deletions src/js/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ export function build(tileURL, spriteURL, glyphURL, locales) {
url: tileURL,
type: "vector",
},
dem: {
attribution:
'<a target="_blank" rel="noopener" href="https://registry.opendata.aws/terrain-tiles/">Terrain Tiles</a>',
type: "raster-dem",
tiles: [
"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png",
],
encoding: "terrarium",
tileSize: 256,
// The actual maxzoom is 15
maxzoom: 12,
},
},
sprite: spriteURL,
light: {
Expand Down
23 changes: 23 additions & 0 deletions src/layer/hillshade.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export const hillshading = {
id: "hillshading",
type: "hillshade",
source: "dem",
maxzoom: 17,
paint: {
"hillshade-exaggeration": [
"interpolate",
["linear"],
["zoom"],
6,
1,
12,
0.7,
16,
0.1,
17,
0,
],
"hillshade-shadow-color": "hsla(30, 14%, 76%, 1)",
"hillshade-highlight-color": "hsla(30, 44%, 99%, 1)",
},
};
3 changes: 3 additions & 0 deletions src/layer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as lyrBackground from "./background.js";
import * as lyrBoundary from "./boundary.js";
import * as lyrConstruction from "./construction.js";
import * as lyrHighwayShield from "./highway_shield.js";
import * as lyrHillshade from "./hillshade.js";
import * as lyrLanduse from "./landuse.js";
import * as lyrOneway from "./oneway.js";
import * as lyrPark from "./park.js";
Expand Down Expand Up @@ -41,6 +42,8 @@ export function build(locales) {
lyrBoundary.stateCasing,
lyrBoundary.countryCasing,

lyrHillshade.hillshading,

lyrWater.waterLine,
lyrWater.waterLineIntermittent,
lyrWater.waterway,
Expand Down