A raster tile layer, also known as an image tile layer, displays imagery such as satellite photography or hillshading. You can combine raster tile layers to enhance the display of a street basemap layer, position the layer on top of existing layers, or position it under existing layers. When positioned above other layers, you need to give the raster tile layer a level of transparency so that users can see through it to the basemap. This combined basemap layer technique is used to enhance overall visualization.
In this tutorial, you add a Hillshade raster tile layer, which is a basemap layer composed of jpeg images, on top of a street basemap layer.
Prerequisites
You need a free ArcGIS developer account to access your dashboard and API keys. The API key must be scoped to access the services used in this tutorial.
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport"content="initial-scale=1,maximum-scale=1,user-scalable=no" /><scriptsrc="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script><linkhref="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css"rel="stylesheet" /><style>html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #323232;
}
</style></head><body><divid="map"></div><script>const apiKey = "YOUR-API-KEY";
const basemapEnum = "ArcGIS:Streets";
const map = new mapboxgl.Map({
container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`,
zoom: 12, // starting zoom center: [-118.805, 34.027] // starting location [longitude, latitude] });
map.once("load", () => {
// This code runs once the base style has finished loading. map.addSource("hillshade", {
type: "raster",
tiles: [
"https://server.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer/tile/{z}/{y}/{x}.jpeg?token=" + apiKey
]
});
// Find the first non-background layer in order to add our raster layer before it.const layers = map.getStyle().layers;
const bottomLayer = layers.find((layer) => layer.type !== "background");
map.addLayer(
{
id: "hillshade-raster",
type: "raster",
source: "hillshade" },
bottomLayer.id
);
layers.forEach((layer) => {
if (layer.type === "fill" && !layer.id.match(/(Water area|Marine area|Bathymetry|Building)/)) {
map.setPaintProperty(layer.id, "fill-opacity", 0.5);
}
});
});
</script></body></html>
Add a raster source
You need to define a source for the raster tiles. This tells the Map how to access the data for the layer, but does not display it.
Inside the load event handler, add a raster source with id hillshade.
While there are several types of source, the most common are vector for vector tiles, raster for raster tiles, and geojson for a set of features represented as GeoJSON.
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport"content="initial-scale=1,maximum-scale=1,user-scalable=no" /><scriptsrc="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script><linkhref="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css"rel="stylesheet" /><style>html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #323232;
}
</style></head><body><divid="map"></div><script>const apiKey = "YOUR-API-KEY";
const basemapEnum = "ArcGIS:Streets";
const map = new mapboxgl.Map({
container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`,
zoom: 12, // starting zoom center: [-118.805, 34.027] // starting location [longitude, latitude] });
map.once("load", () => {
// This code runs once the base style has finished loading. map.addSource("hillshade", {
type: "raster",
tiles: [
"https://server.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer/tile/{z}/{y}/{x}.jpeg?token=" + apiKey
]
});
// Find the first non-background layer in order to add our raster layer before it.const layers = map.getStyle().layers;
const bottomLayer = layers.find((layer) => layer.type !== "background");
map.addLayer(
{
id: "hillshade-raster",
type: "raster",
source: "hillshade" },
bottomLayer.id
);
layers.forEach((layer) => {
if (layer.type === "fill" && !layer.id.match(/(Water area|Marine area|Bathymetry|Building)/)) {
map.setPaintProperty(layer.id, "fill-opacity", 0.5);
}
});
});
</script></body></html>
At the top right, click Run. You should see the hillshade layer only.
Adjust the basemap
By default, the hillshade layer is added on top of all the basemap layers. To visually combine hillshading with roads and park layers, you need to make two changes.
Move the hillshade layer below every layer except the background layer. You do this by passing the id of the next layer as an extra argument to map.addLayer.
Reduce the opacity of most fill layers so the hillshade layer can be seen through them. In the ArcGIS:Streets basemap, this includes several layers whose ids begin with Water area, Marine area, Bathymetry or Building. You can use map.getStyle to get the current style, and its layers property to access all layers. Use map.setPaintProperty to change the fill-opacity for each layer.
In the load handler, find the id of the first non-background layer. Modify your addLayer call to insert the raster layer before that layer.
Add line.Add line.Add line.Add line.
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport"content="initial-scale=1,maximum-scale=1,user-scalable=no" /><scriptsrc="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script><linkhref="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css"rel="stylesheet" /><style>html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #323232;
}
</style></head><body><divid="map"></div><script>const apiKey = "YOUR-API-KEY";
const basemapEnum = "ArcGIS:Streets";
const map = new mapboxgl.Map({
container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`,
zoom: 12, // starting zoom center: [-118.805, 34.027] // starting location [longitude, latitude] });
map.once("load", () => {
// This code runs once the base style has finished loading. map.addSource("hillshade", {
type: "raster",
tiles: [
"https://server.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer/tile/{z}/{y}/{x}.jpeg?token=" + apiKey
]
});
// Find the first non-background layer in order to add our raster layer before it.const layers = map.getStyle().layers;
const bottomLayer = layers.find((layer) => layer.type !== "background");
map.addLayer(
{
id: "hillshade-raster",
type: "raster",
source: "hillshade" },
bottomLayer.id
);
layers.forEach((layer) => {
if (layer.type === "fill" && !layer.id.match(/(Water area|Marine area|Bathymetry|Building)/)) {
map.setPaintProperty(layer.id, "fill-opacity", 0.5);
}
});
});
</script></body></html>
Set 50% fill-opacity for every fill layer except water and building layers.
Add line.Add line.Add line.Add line.Add line.
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport"content="initial-scale=1,maximum-scale=1,user-scalable=no" /><scriptsrc="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js"></script><linkhref="https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css"rel="stylesheet" /><style>html,
body,
#map {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #323232;
}
</style></head><body><divid="map"></div><script>const apiKey = "YOUR-API-KEY";
const basemapEnum = "ArcGIS:Streets";
const map = new mapboxgl.Map({
container: "map", // the id of the div element style: `https://basemaps-api.arcgis.com/arcgis/rest/services/styles/${basemapEnum}?type=style&apiKey=${apiKey}`,
zoom: 12, // starting zoom center: [-118.805, 34.027] // starting location [longitude, latitude] });
map.once("load", () => {
// This code runs once the base style has finished loading. map.addSource("hillshade", {
type: "raster",
tiles: [
"https://server.arcgisonline.com/arcgis/rest/services/Elevation/World_Hillshade/MapServer/tile/{z}/{y}/{x}.jpeg?token=" + apiKey
]
});
// Find the first non-background layer in order to add our raster layer before it.const layers = map.getStyle().layers;
const bottomLayer = layers.find((layer) => layer.type !== "background");
map.addLayer(
{
id: "hillshade-raster",
type: "raster",
source: "hillshade" },
bottomLayer.id
);
layers.forEach((layer) => {
if (layer.type === "fill" && !layer.id.match(/(Water area|Marine area|Bathymetry|Building)/)) {
map.setPaintProperty(layer.id, "fill-opacity", 0.5);
}
});
});
</script></body></html>
Run the app
In CodePen, run your code to display the map.
Your map should display a semi-transparent hillshade layer overlaid over a basemap. You should see the hillshade layer combined with other layers, with labels, roads, buildings and water areas clearly visible over the top.