mapbox / mapbox/mapbox-gl-js

Custom source enhancement

Open
#13,093 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

auto-triaged feature :green_apple:
Dominant language
TypeScript
Stars
12.4k
Forks
2.4k
PR merge metrics
No merged PRs in 30d

Description

## Motivation

Currently, the custom data source of mapbox only supports Raster type, Judging by the following logic:

```js
function isRaster(data: any): boolean {
return data instanceof ImageData ||
data instanceof HTMLCanvasElement ||
data instanceof ImageBitmap ||
data instanceof HTMLImageElement;
}
```

This is sufficient in most cases, but it brings some limitations when we need some non-standard raster data,such as TIFF/netcdf/geojson

## Design Alternatives

Based on the above objectives, if we can rewrite the loadTile, loadTileData of [custom_source](https://github1s.com/mapbox/mapbox-gl-js/blob/HEAD/src/source/custom_source.js), it will bring better scalability.The relevant logic is implemented by the user implementation, custom_source can support parsing of multiple data types

## Design

### Mock-Up

### Concepts

### Implementation

loadTileData:

```diff
loadTileData(tile: Tile, data: T): void {
- tile.setTexture((data: any), this._map.painter);
+ if (this._implementation.loadTileData) {
+ this._implementation.loadTileData(tile, data, this._map.painter);
+ } else {
+ // Only raster data supported at the moment
+ tile.setTexture((data: any), this._map.painter);
+ }
}
```

loadTile:

```diff
loadTile(tile: Tile, callback: Callback): void {
+ if (this._implementation.loadTileOverride) {
+ this._implementation.loadTileOverride(tile, callback, this._map);
+ } else {
const {x, y, z} = tile.tileID.canonical;
const controller = new window.AbortController();
const signal = controller.signal;

// $FlowFixMe[prop-missing]
tile.request = Promise
.resolve(this._implementation.loadTile({x, y, z}, {signal}))
.then(tileLoaded.bind(this))
.catch(error => {
// silence AbortError
if (error.code === 20) return;
tile.state = 'errored';
callback(error);
});

// $FlowFixMe[prop-missing]
tile.request.cancel = () => controller.abort();

// $FlowFixMe[missing-this-annot]
function tileLoaded(data: ?T) {
delete tile.request;

if (tile.aborted) {
tile.state = 'unloaded';
return callback(null);
}

// If the implementation returned `undefined` as tile data,
// mark the tile as `errored` to indicate that we have no data for it.
// A map will render an overscaled parent tile in the tile’s space.
if (data === undefined) {
tile.state = 'errored';
return callback(null);
}

// If the implementation returned `null` as tile data,
// mark the tile as `loaded` and use an an empty image as tile data.
// A map will render nothing in the tile’s space.
if (data === null) {
const emptyImage = {width: this.tileSize, height: this.tileSize, data: null};
this.loadTileData(tile, (emptyImage: any));
tile.state = 'loaded';
return callback(null);
}

if (!isRaster(data)) {
tile.state = 'errored';
return callback(new Error(`Can't infer data type for ${this.id}, only raster data supported at the moment`));
}

this.loadTileData(tile, data);
tile.state = 'loaded';
callback(null);
}
+ }
}
```

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/source/custom_source.js and read the existing loadTile, loadTileData, and isRaster flow. Trace how custom source implementations pass tile data into rendering, then define and verify the extension points for user-controlled loading and tile-data handling so non-raster data can be supported without breaking existing raster behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.