Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion docs/api-reference/geo-layers/terrain-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ new deck.TerrainLayer({});

## Properties

When in Tiled Mode, inherits from all [TileLayer](./tile-layer.md) properties. Forwards `wireframe` property to [SimpleMeshLayer](../mesh-layers/simple-mesh-layer.md).
When in Tiled Mode, inherits from all [TileLayer](./tile-layer.md) properties. Tiled terrain
forwards `renderPlaceholder` to its internal `TileLayer`; this can be used to render loading
footprints before terrain meshes are available. Forwards `wireframe` property to
[SimpleMeshLayer](../mesh-layers/simple-mesh-layer.md).



Expand Down
42 changes: 42 additions & 0 deletions docs/api-reference/geo-layers/tile-layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,10 @@ If not supplied, the `maxCacheByteSize` is set to `Infinity`.

How the tile layer refines the visibility of tiles. When zooming in and out, if the layer only shows tiles from the current zoom level, then the user may observe undesirable flashing while new data is loading. By setting `refinementStrategy` the layer can attempt to maintain visual continuity by displaying cached data from a different zoom level before data is available.

`refinementStrategy` only reuses loaded tile content that is already in the cache. To render
synthetic content while a selected tile has no loaded content and no cached ancestor or child is
visible, use [`renderPlaceholder`](#renderplaceholder).

This prop accepts one of the following:

* `'best-available'`: If a tile in the current viewport is waiting for its data to load, use cached content from the closest zoom level to fill the empty space. This approach minimizes the visual flashing due to missing content.
Expand Down Expand Up @@ -358,6 +362,44 @@ Note that the following sub layer props are overridden by `TileLayer` internally
- `visible` (toggled based on tile visibility)
- `highlightedObjectIndex` (set based on the parent layer's highlight state)

#### `renderPlaceholder` (Function, optional) {#renderplaceholder}

Renders one or an array of Layer instances for a selected tile while its data is loading.

This prop is disabled by default. When supplied, it is called for selected tiles that have no loaded
content and no generated sublayers. With the default `refinementStrategy: 'best-available'`, cached
ancestor or child content still takes priority, so placeholders only fill cold-start or cache-miss
gaps. With `refinementStrategy: 'no-overlap'`, placeholders are shown instead of cached refinement
content for selected loading tiles.

The callback receives all the `TileLayer` props and the following props:

* `id` (string): A unique id for this placeholder sublayer
* `data` (null): Placeholder tiles do not have loaded tile data
* `bounds` (number[4]): Bounds of the tile in `[left, bottom, right, top]` order
* `tile` ([Tile](#tile))

- Default: `null`

For raster tiles, return a `BitmapLayer` that spans `props.bounds`. Set `pickable: false` if
placeholder layers should not participate in picking.

```ts
renderPlaceholder: props => {
const {data, bounds, ...otherProps} = props;

return new BitmapLayer(otherProps, {
image: 'data:image/png;base64,...',
bounds,
pickable: false,
opacity: 0.35
});
}
```

Placeholder sublayers do not make the tile or layer loaded. `isLoaded`, `onViewportLoad`, tile cache
behavior, and tile error handling continue to depend on the real tile request.

#### `zRange` (number[2], optional) {#zrange}

An array representing the height range of the content in the tiles, as `[minZ, maxZ]`. This is designed to support tiles with 2.5D content, such as buildings or terrains. At high pitch angles, such a tile may "extrude into" the viewport even if its 2D bounding box is out of view. Therefore, it is necessary to provide additional information for the layer to behave correctly. The value of this prop is used for two purposes: 1) to determine the necessary tiles to load and/or render; 2) to determine the possible intersecting tiles during picking.
Expand Down
40 changes: 38 additions & 2 deletions examples/website/image-tile/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors

/* global fetch, DOMParser */
/* global fetch, DOMParser, setTimeout */
import React, {useState, useEffect} from 'react';
import {createRoot} from 'react-dom/client';

Expand All @@ -24,6 +24,11 @@ const INITIAL_VIEW_STATE: OrthographicViewState = {

const ROOT_URL =
'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/image-tiles/moon.image';
const PLACEHOLDER_IMAGE =
'data:image/svg+xml;charset=utf-8,' +
'%3Csvg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8"%3E' +
'%3Crect width="8" height="8" fill="%23242a2e"/%3E' +
'%3Cpath d="M0 8 8 0" stroke="%23404a50" stroke-width="1"/%3E%3C/svg%3E';

function getTooltip({tile, bitmap}: TileLayerPickingInfo<ImageBitmap, BitmapLayerPickingInfo>) {
if (tile && bitmap) {
Expand All @@ -35,11 +40,19 @@ function getTooltip({tile, bitmap}: TileLayerPickingInfo<ImageBitmap, BitmapLaye
return null;
}

function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}

export default function App({
autoHighlight = true,
showPlaceholders = true,
loadDelay = 0,
onTilesLoad
}: {
autoHighlight?: boolean;
showPlaceholders?: boolean;
loadDelay?: number;
onTilesLoad?: () => void;
}) {
const [dimensions, setDimensions] = useState<{width: number; height: number; tileSize: number}>();
Expand Down Expand Up @@ -85,14 +98,37 @@ export default function App({
minZoom: -7,
maxZoom: 0,
extent: [0, 0, dimensions.width, dimensions.height],
getTileData: ({index}) => {
getTileData: async ({index}) => {
const {x, y, z} = index;
if (loadDelay > 0) {
await sleep(loadDelay);
}
return load(
`${ROOT_URL}/moon.image_files/${15 + z}/${x}_${y}.jpeg`
) as Promise<ImageBitmap>;
},
onViewportLoad: onTilesLoad,

renderPlaceholder: showPlaceholders
? props => {
const {width, height} = dimensions;
const {bounds} = props;
const otherProps = {...props} as Partial<typeof props>;
delete otherProps.data;
delete otherProps.bounds;
return new BitmapLayer(otherProps, {
image: PLACEHOLDER_IMAGE,
bounds: [
clamp(bounds[0], 0, width),
clamp(bounds[1], 0, height),
clamp(bounds[2], 0, width),
clamp(bounds[3], 0, height)
],
pickable: false,
opacity: 0.5
});
}
: undefined,
renderSubLayers: props => {
const [[left, bottom], [right, top]] = props.tile.boundingBox;
const {width, height} = dimensions;
Expand Down
15 changes: 9 additions & 6 deletions examples/website/map-tile/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
This is a standalone version of the [OpenStreetMap](https://www.openstreetmap.org/) example using TileLayer and BitmapLayer
on [deck.gl](http://deck.gl) website.
This is a standalone version of the GlobeView terrain tile example using TerrainLayer
on the [deck.gl](http://deck.gl) website.

### Usage

Copy the content of this folder to your project.
Copy the content of this folder to your project.

```bash
# install dependencies
Expand All @@ -14,9 +14,12 @@ yarn
npm start
```

### Data Source
### Data Sources

The sample tiles are loaded from [OpenStreetMap](https://www.openstreetmap.org).
The sample elevation tiles are loaded from the
[AWS Open Data Terrain Tiles](https://registry.opendata.aws/terrain-tiles/) dataset.
The satellite texture is loaded from
[ArcGIS World Imagery](https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9).

To use your own data, check out
the [documentation of TileLayer](../../../docs/api-reference/geo-layers/tile-layer.md).
the [documentation of TerrainLayer](../../../docs/api-reference/geo-layers/terrain-layer.md).
Loading
Loading