Docs / Basics / Raster layer

Raster layer

Overlay any XYZ tile set by giving a URL template — external tiles such as the GSI maps of Japan work as-is.

ANDROID
com.mapconductor:core
iOS
MapConductorCore
REACT
@mapconductor/js-sdk-react
Platform

01 · Usage

Pass a URL template as the source. Opacity and zoom range are controlled on the layer.

RasterLayerScreen.kt · Jetpack Compose
val rasterLayerState = RasterLayerState(
    id = "gsi-raster",
    source = RasterLayerSource.UrlTemplate(
        template = "https://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png",
        tileSize = 256,
        minZoom = 5,
        maxZoom = 15,
    ),
    opacity = 0.75f,
)

MapLibreMapView(state = mapState) {
    RasterLayer(rasterLayerState)
}

02 · Options

Option
Default
Description
template
Tile URL template containing {z}/{x}/{y}.
tileSize
512
Tile edge length in pixels.
minZoom / maxZoom
none
Zoom range in which the layer is shown; unset means shown at all zooms.
attributionRules
[]
Attribution text rules per zoom and area; set on the source.
opacity
1.0
Opacity of the whole layer (set on the layer).
visible
true
Show or hide the layer.
zIndex
0
Stacking order relative to other layers.
userAgent
MapConductor/…
User-Agent used when fetching tiles. Support varies by provider (see below).
extraHeaders
none
Extra headers sent when fetching tiles, e.g. an auth token. Support varies by provider (see below).

03 · Header support

Tiles are fetched by each provider's map SDK, and whether it exposes a hook for rewriting requests differs per SDK. Where there is no hook, the values are ignored and a warning is logged at runtime. The table below reflects what was actually observed by receiving the tile requests (on device for native, in the browser for web).

On the web, userAgent has no effect on any provider: browsers forbid overriding User-Agent and no SDK can work around it. The property remains for React Native, where the value is passed to the native SDK and does take effect — so the same component code runs on both web and RN.

Provider
iOS
Android
Web (extraHeaders)
Notes
MapLibre
iOS uses the MLNNetworkConfiguration hook; Android swaps the OkHttp client; the web uses maplibre-gl’s transformRequest. All three apply headers only to requests bound for the tile host.
MapTiler
On iOS this uses the same mechanism as MapLibre. The Android MapTiler SDK runs inside a WebView, so headers cannot be injected from the native side.
MapKit
iOS-only provider.
HERE
On iOS the tiles go through a local proxy only when headers are set, which adds one hop.
Google Maps
userAgent
Android fetches tiles itself, so both work. GMSURLTileLayer on iOS exposes only userAgent, so extraHeaders is ignored.
Mapbox
The iOS and Android SDKs expose no public API for rewriting requests. On the web, mapbox-gl has transformRequest, so the web is supported.
ArcGIS
Same as above.
TomTom
Same as above.
Longdo
Same as above.
Leaflet
Web-only. When headers are set, tiles are fetched with fetch() and swapped in as a blob.
OpenLayers
Web-only. Same approach, via a custom tileLoadFunction.
Azure Maps
Web-only. Uses transformRequest.
Cesium
yes (unverified)
Web-only. Implemented by passing a Resource with headers, but not yet verified by measurement because of an unrelated issue in the sample app.

If your tile server requires headers, pick a provider that supports them. Providers without support can still be used when the token can be passed as a URL query parameter instead.

04 · Sample

GSI tiles

The sample switches between relief and standard GSI layers with an opacity slider; attribution switches automatically through attributionRules.

What the video shows · Android + MapLibreKotlin · Jetpack Compose
var opacity by remember { mutableFloatStateOf(0.75f) }
var relief by remember { mutableStateOf(true) }

val layerState = remember { RasterLayerState(id = "gsi-raster") }

// Both source and opacity can be reassigned; the layer is not rebuilt
LaunchedEffect(relief, opacity) {
    layerState.source = RasterLayerSource.UrlTemplate(
        template = if (relief) {
            "https://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png"
        } else {
            "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png"
        },
        tileSize = 256,
        minZoom = 5,
        maxZoom = 15,
    )
    layerState.opacity = opacity
}

MapLibreMapView(state = mapViewState) {
    RasterLayer(layerState)
}

Slider(value = opacity, onValueChange = { opacity = it })
Switch(checked = relief, onCheckedChange = { relief = it })
Sample video · overlaying raster tiles
Video not shot yetAn external tile server laid over the base map, the tiles swapping as the zoom changes.

Related pages