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

TileLayer: add embed demo example #2814

Merged
merged 1 commit into from Mar 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
70 changes: 45 additions & 25 deletions docs/layers/tile-layer.md
@@ -1,3 +1,9 @@
<!-- INJECT:"TileLayerDemo" -->

<p class="badges">
<img src="https://img.shields.io/badge/64--bit-support-blue.svg?style=flat-square" alt="64-bit" />
</p>

# TileLayer

This TileLayer takes in a function `getTileData` that fetches tiles, and renders it in a GeoJsonLayer or with the layer returned in `renderSubLayers`.
Expand All @@ -8,33 +14,47 @@ import {TileLayer} from '@deck.gl/geo-layers';
import {VectorTile} from '@mapbox/vector-tile';
import Protobuf from 'pbf';

function getTileData({x, y, z}) {
return fetch(`https://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v7/${z}/${x}/${y}.vector.pbf?access_token=${MAPBOX_TOKEN}`)
.then(response => response.arrayBuffer())
.then(buffer => vectorTileToGeoJSON(buffer, x, y, z));
}

function vectorTileToGeoJSON(buffer, x, y, z) {
const tile = new VectorTile(new Protobuf(buffer));
const features = [];
for (const layerName in tile.layers) {
const vectorTileLayer = tile.layers[layerName];
for (let i = 0; i < vectorTileLayer.length; i++) {
const vectorTileFeature = vectorTileLayer.feature(i);
const feature = vectorTileFeature.toGeoJSON(x, y, z);
features.push(feature);
}
}
return features;
}

export const App = ({viewport}) => {

const layer = new TileLayer({
stroked: false,

getLineColor: [192, 192, 192],
getFillColor: [140, 170, 180],
getTileData

getLineWidth: f => {
if (f.properties.layer === 'transportation') {
switch (f.properties.class) {
case 'primary':
return 12;
case 'motorway':
return 16;
default:
return 6;
}
}
return 1;
},
lineWidthMinPixels: 1,

getTileData: ({x, y, z}) => {
const mapSource = `https://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v7/${z}/${x}/${y}.vector.pbf?access_token=${MapboxAccessToken}`;
return fetch(mapSource)
.then(response => response.arrayBuffer())
.then(buffer => {
const tile = new VectorTile(new Protobuf(buffer));
const features = [];
for (const layerName in tile.layers) {
const vectorTileLayer = tile.layers[layerName];
for (let i = 0; i < vectorTileLayer.length; i++) {
const vectorTileFeature = vectorTileLayer.feature(i);
const feature = vectorTileFeature.toGeoJSON(x, y, z);
features.push(feature);
}
}
return features;
});
}
});
return <DeckGL {...viewport} layers={[layer]} />;
};
Expand All @@ -46,13 +66,13 @@ Inherits from all [Base Layer](/docs/api-reference/layer.md) properties, along w

##### `maxZoom` (Number|Null, optional)

The maximum zoom level of the tiles from consumers' data. If provided, and the current map zoom level is greater than `maxZoom`, we will fetch data at `maxZoom` instead of the current zoom level.
Use tiles from this level when over-zoomed.

- Default: `null`

##### `minZoom` (Number, optional)

The minimum zoom level of the tiles from consumers' data. If provided, and the current map zoom level is smaller than `minZoom`, we will fetch data at `minZoom` instead of the current zoom level.
Hide tiles when under-zoomed.

- Default: 0

Expand All @@ -72,7 +92,7 @@ The maximum cache size for a tile layer. If not defined, it is calculated using

##### `getTileData` (Function, optional)

`getTileData` is a function that takes `{x, y, z}` as parameters, and returns a promise, which resolves to data in tile z-x-y.
`getTileData` given x, y, z indices of the tile, returns a Promise that resolves to the decoded tile data.

- Default: `getTileData: ({x, y, z}) => Promise.resolve(null)`

Expand All @@ -84,7 +104,7 @@ The maximum cache size for a tile layer. If not defined, it is calculated using

##### `renderSubLayers` (Function, optional))

Renders a sub-layer with the `data` prop being the resolved value of `getTileData`, and other props that are passed in the `TileLayer`
Renders one or an array of Layer instances with `data` resolved from `getTileData` and other `TileLayer` props.

- Default: `props => new GeoJsonLayer(props)`

Expand Down
1 change: 0 additions & 1 deletion modules/geo-layers/src/tile-layer/tile-layer.js
Expand Up @@ -84,7 +84,6 @@ export default class TileLayer extends CompositeLayer {
}

renderLayers() {
// eslint-disable-next-line no-unused-vars
const {renderSubLayers, visible} = this.props;
const z = this.getLayerZoomLevel();
return this.state.tiles.map(tile => {
Expand Down
2 changes: 2 additions & 0 deletions website/package.json
Expand Up @@ -16,6 +16,7 @@
"lint": "eslint src --ignore-pattern workers"
},
"dependencies": {
"@mapbox/vector-tile": "^1.3.1",
"@tweenjs/tween.js": "^16.7.0",
"autobind-decorator": "^1.3.3",
"d3-color": "^1.0.1",
Expand All @@ -24,6 +25,7 @@
"expr-eval": "^1.0.0",
"highlight.js": "^9.7.0",
"marked": "^0.3.6",
"pbf": "^3.2.0",
"prop-types": "^15.5.8",
"rbush": "^2.0.1",
"react": "^16.0.0",
Expand Down
44 changes: 27 additions & 17 deletions website/src/components/demos/layer-demo-base.js
@@ -1,7 +1,6 @@
import React, {Component} from 'react';
import DeckGL from 'deck.gl';
import autobind from 'autobind-decorator';
import {setParameters} from 'luma.gl';

import {MAPBOX_STYLES} from '../../constants/defaults';
import {getLayerParams} from '../../utils/layer-params';
Expand All @@ -16,9 +15,8 @@ const defaultViewport = {
};

export default function createLayerDemoClass(settings) {

const renderLayer = (data, params, extraProps = {}) => {
if (!data) {
const renderLayer = (data, allowMissingData, params, extraProps = {}) => {
if (!data && !allowMissingData) {
return null;
}

Expand All @@ -34,7 +32,6 @@ export default function createLayerDemoClass(settings) {
};

class DemoClass extends Component {

static get data() {
return {
url: settings.dataUrl
Expand All @@ -53,9 +50,16 @@ export default function createLayerDemoClass(settings) {
const name = settings.Layer.layerName;
return (
<div>
<h3>{ name }</h3>
<p>Explore {name}'s API <br/>
<a href={settings.dataUrl} target="_new">Sample data</a></p>
<h3>{name}</h3>
<p>
Explore {name}
's API <br />
{settings.dataUrl && (
<a href={settings.dataUrl} target="_new">
Sample data
</a>
)}
</p>
</div>
);
}
Expand All @@ -67,7 +71,8 @@ export default function createLayerDemoClass(settings) {
};
}

@autobind _onHover(info) {
@autobind
_onHover(info) {
this.setState({hoveredItem: info});
}

Expand All @@ -76,12 +81,17 @@ export default function createLayerDemoClass(settings) {
if (hoveredItem && hoveredItem.index >= 0) {
const {formatTooltip} = settings;
const info = formatTooltip ? formatTooltip(hoveredItem.object) : hoveredItem.index;
return info && (
<div className="tooltip"
style={{left: hoveredItem.x, top: hoveredItem.y}}>
{ info.toString().split('\n')
.map((str, i) => <p key={i}>{str}</p>) }
</div>
return (
info && (
<div className="tooltip" style={{left: hoveredItem.x, top: hoveredItem.y}}>
{info
.toString()
.split('\n')
.map((str, i) => (
<p key={i}>{str}</p>
))}
</div>
)
);
}
return null;
Expand All @@ -97,8 +107,8 @@ export default function createLayerDemoClass(settings) {

return (
<div>
<DeckGL pickingRadius={5} viewState={viewState} layers={ layers } />
{ this._renderTooltip() }
<DeckGL pickingRadius={5} viewState={viewState} layers={layers} />
{this._renderTooltip()}
</div>
);
}
Expand Down
53 changes: 52 additions & 1 deletion website/src/components/demos/layer-demos.js
@@ -1,3 +1,6 @@
/* global fetch */
import {VectorTile} from '@mapbox/vector-tile';
import Protobuf from 'pbf';
import createLayerDemoClass from './layer-demo-base';
import {DATA_URI} from '../../constants/defaults';

Expand All @@ -14,7 +17,8 @@ import {
HexagonLayer,
PolygonLayer,
GeoJsonLayer,
PointCloudLayer
PointCloudLayer,
TileLayer
} from 'deck.gl';
import ContourLayer from '@deck.gl/aggregation-layers/contour-layer/contour-layer';

Expand Down Expand Up @@ -214,6 +218,53 @@ export const TextLayerDemo = createLayerDemoClass({
}
});

export const TileLayerDemo = createLayerDemoClass({
Layer: TileLayer,
formatTooltip: f => JSON.stringify(f.properties),
allowMissingData: true,
props: {
stroked: false,
opacity: 1,

getLineColor: [192, 192, 192],
getFillColor: [140, 170, 180],

getLineWidth: f => {
if (f.properties.layer === 'transportation') {
switch (f.properties.class) {
case 'primary':
return 12;
case 'motorway':
return 16;
default:
return 6;
}
}
return 1;
},
lineWidthMinPixels: 1,

getTileData: ({x, y, z}) => {
const mapSource = `https://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v7/${z}/${x}/${y}.vector.pbf?access_token=${MapboxAccessToken}`;
return fetch(mapSource)
.then(response => response.arrayBuffer())
.then(buffer => {
const tile = new VectorTile(new Protobuf(buffer));
const features = [];
for (const layerName in tile.layers) {
const vectorTileLayer = tile.layers[layerName];
for (let i = 0; i < vectorTileLayer.length; i++) {
const vectorTileFeature = vectorTileLayer.feature(i);
const feature = vectorTileFeature.toGeoJSON(x, y, z);
features.push(feature);
}
}
return features;
});
}
}
});

export const ContourLayerDemo = createLayerDemoClass({
Layer: ContourLayer,
dataUrl: `${DATA_URI}/sf-bike-parking.json`,
Expand Down