Skip to content

Commit

Permalink
Refactor Source interface to allow/prepare for extensibility (#2667)
Browse files Browse the repository at this point in the history
* Major refactor to Source interface

 * Invert the TilePyramid / Source dependency
 * Change Source from class-based to factory-based interface
 * Add WorkerSource concept, allowing Source type to register worker-side functionality
 * Separate GeoJSONSource and ClusteredGeoJSONSource

* Add optional callback for dispatcher.broadcast

* Move coveringZoomLevel, coveringTiles to Transform

* Refactor raster source to new interface

* WIP - refactor video source

* Reload pyramid in onChange()

* Reinstate query*Features

* Restore validateStyle to top of style init

* Small edits from PR comments

* Go back to mixing in Evented in Source impls

* Drop Source.is

Removes the ability to create a `Source` instance independent of the
`Map` (or, actually, `Style` instance).

* Enforce correct source.id value

* s/cb/callback

* Fix extend/inherit and other minor errors

* Use more descriptive names for Source methods

* Rename TilePyramid to SourceCache

* Remove bucketStats

* Remove unused var

* Simplify GeoJSONWorkerSource

* Fix geojson_source.test

* Fix source_cache tests

* s/tile_pyramid/source_cache

* Restore 'ignore reload' test, now in source_cache

* Fix vector_tile_source.test

* Fix style.test

* Fix map tests

* Remove async loading of core source types

* s/query-features.js/query_features.js

* Replace old queryRenderedFeature edge case test

* Replace old GeoJSONSource test

Instead of checking whether GeoJSONSource#setData results in the TilePyramid dropping its loaded tiles, we now check whether SourceCache, on observing a `change` event from its underlying source, seeks to re-loadTile its tiles.

* Improve getSource API

* Treat errored source as loaded()

* Add some docs to geojson_worker_source

* Add supercluster-specific debug page

* Fix typo

* Fix 'geojson / reparse-overscaled' render test

* Fix lint

* Correctly handle Source error events

* WIP - add more docs

* Fix generated doc output

* Do not call prepare() unless source is ready

* Fix VideoSource

* Add image.html debug page

* Fix ImageSource

* Fix render tests

* Revise addSourceType API and add basic tests.

* Make GeoJSONSource more hackable

* Suppress signature and params in @interface docs

Related issue upstream: documentationjs/documentation#461

* Improve custom source type docs

* Update GeoJSONSource,VideoSource,ImageSource docs

* Throw from addSource if source.type is missing

* Update GeoJSON source examples

* load-tilejson => load_tilejson

* Move _sendDataToWorker to setData

* Revert to new-based API for sources

* Drop extra cluster stuff from default debug page.

Use cluster.html instead.

* Dedupe debug & test-suite assets

* Factor VectorTileWorkerSource out of Worker

* Fix tests

* Update registerWorkerSource to current WorkerSource interface

* Fix test after rebase

* Image/Video: tile.loaded|errored => tile.state

* Restore *.tile events on sources

* Hide custom source classes / interfaces from documentation

We should validate the custom source architecture and build some demo
sources before documenting the internals publicly.

* Namespace mapbox-gl-test-suite files in debug server

* Add source docs

* Remove GeoJSONSource, VideoSource, ImageSource from the public interface

* Minor GeoJSONSource simplification
  • Loading branch information
anandthakker authored and lucaswoj committed Jul 20, 2016
1 parent 302aadd commit def9cb5
Show file tree
Hide file tree
Showing 47 changed files with 2,477 additions and 1,745 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## master

#### Breaking Changes

* The `GeoJSONSource`, `VideoSource`, `ImageSource` constructors are now private. Please use `map.addSource({...})` to create sources and `map.getSource(...).setData(...)` to update GeoJSON sources.

## 0.21.0 (July 13 2016)

#### Breaking Changes
Expand Down
4 changes: 2 additions & 2 deletions debug/circles.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
<script>
var map = window.map = new mapboxgl.Map({
container: 'map',
zoom: 12.5,
zoom: 3,
center: [-77.01866, 38.888],
style: 'mapbox://styles/mapbox/streets-v9',
hash: true
Expand All @@ -68,7 +68,7 @@

map.addSource('circles', {
"type": "geojson",
"data": "random.geojson"
"data": "mapbox-gl-test-suite/data/places.geojson"
});

map.addLayer({
Expand Down
167 changes: 167 additions & 0 deletions debug/cluster.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<!DOCTYPE html>
<html>
<head>
<title>Mapbox GL JS debug page</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

<link rel='stylesheet' href='../dist/mapbox-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
#checkboxes {
position: absolute;
background: #fff;
top:0;
left:0;
padding:10px;
}
#buffer {
position: absolute;
top:100px;
left:0;
pointer-events: none;
}
#buffer div {
background-color: #fff;
padding: 5px 0;
text-indent: 10px;
white-space: nowrap;
text-shadow:
-1px -1px 0 #fff,
1px -1px 0 #fff,
-1px 1px 0 #fff,
1px 1px 0 #fff;
}
</style>
</head>

<body>
<div id='map'></div>
<div id='checkboxes'>
<input id='show-tile-boundaries-checkbox' name='show-tile-boundaries' type='checkbox'> <label for='show-tile-boundaries'>tile debug</label><br />
<input id='show-symbol-collision-boxes-checkbox' name='show-symbol-collision-boxes' type='checkbox'> <label for='show-symbol-collision-boxes'>collision debug</label><br />
<input id='show-overdraw-checkbox' name='show-overdraw' type='checkbox'> <label for='show-overdraw'>overdraw debug</label><br />
<input id='buffer-checkbox' name='buffer' type='checkbox'> <label for='buffer'>buffer stats</label>
</div>

<div id='buffer' style="display:none">
<em>Waiting for data...</em>
</div>

<script src='mapbox-gl.js'></script>
<script src='access-token.js'></script>

<script>
var style = {
"version": 8,
"metadata": {
"test": {
"native": false,
"width": 512,
"height": 512
}
},
"center": [
0,
0
],
"zoom": 0,
"sources": {
"geojson": {
"type": "geojson",
"data": "mapbox-gl-test-suite/data/places.geojson",
"cluster": true,
"clusterRadius": 25
}
},
"glyphs": "mapbox-gl-test-suite/glyphs/{fontstack}/{range}.pbf",
"layers": [
{
"id": "cluster",
"type": "circle",
"source": "geojson",
"filter": [
"==",
"cluster",
true
],
"paint": {
"circle-color": "rgba(0, 200, 0, 1)",
"circle-radius": 20
}
},
{
"id": "cluster_label",
"type": "symbol",
"source": "geojson",
"filter": [
"==",
"cluster",
true
],
"layout": {
"text-field": "{point_count}",
"text-font": [
"Open Sans Semibold",
"Arial Unicode MS Bold"
],
"text-size": 12,
"text-allow-overlap": true,
"text-ignore-placement": true
}
},
{
"id": "unclustered_point",
"type": "circle",
"source": "geojson",
"filter": [
"!=",
"cluster",
true
],
"paint": {
"circle-color": "rgba(0, 0, 200, 1)",
"circle-radius": 10
}
}
]
}

var map = window.map = new mapboxgl.Map({
container: 'map',
style: style,
hash: true
});

map.addControl(new mapboxgl.Navigation());
map.addControl(new mapboxgl.Geolocate());

document.getElementById('show-tile-boundaries-checkbox').onclick = function() {
map.showTileBoundaries = !!this.checked;
};

document.getElementById('show-symbol-collision-boxes-checkbox').onclick = function() {
map.showCollisionBoxes = !!this.checked;
};

document.getElementById('show-overdraw-checkbox').onclick = function() {
map.showOverdrawInspector = !!this.checked;
};

document.getElementById('buffer-checkbox').onclick = function() {
document.getElementById('buffer').style.display = this.checked ? 'block' : 'none';
};

// keyboard shortcut for comparing rendering with Mapbox GL native
document.onkeypress = function(e) {
if (e.charCode === 111 && !e.shiftKey && !e.metaKey && !e.altKey) {
var center = map.getCenter();
location.href = "mapboxgl://?center=" + center.lat + "," + center.lng + "&zoom=" + map.getZoom() + "&bearing=" + map.getBearing();
return false;
}
};
</script>

</body>
</html>
60 changes: 60 additions & 0 deletions debug/image.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<title>Mapbox GL JS debug page</title>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel='stylesheet' href='../dist/mapbox-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
</style>
</head>

<div id='map'></div>

<script src='mapbox-gl.js'></script>
<script src='access-token.js'></script>

<script>
var imageStyle = {
"version": 8,
"sources": {
"image": {
"type": "image",
"url": "mapbox-gl-test-suite/image/0.png",
"coordinates": [
[-122.51596391201019, 37.56238816766053],
[-122.51467645168304, 37.56410183312965],
[-122.51309394836426, 37.563391708549425],
[-122.51423120498657, 37.56161849366671]
]
}
},
"layers": [{
"id": "background",
"type": "background",
"paint": {
"background-color": "rgb(4,7,14)"
}
}, {
"id": "image",
"type": "raster",
"source": "image"
}]
};

var map = new mapboxgl.Map({
container: 'map',
minZoom: 14,
zoom: 17,
center: [-122.514426, 37.562984],
bearing: -96,
style: imageStyle,
hash: false
});
</script>

</body>
</html>
2 changes: 1 addition & 1 deletion debug/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
map.on('load', function() {
map.addSource('geojson', {
"type": "geojson",
"data": "route.json"
"data": "mapbox-gl-test-suite/data/linestring.geojson"
});

map.addLayer({
Expand Down
49 changes: 19 additions & 30 deletions debug/featuresIn.html → debug/queryFeatures.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,17 @@
var map = new mapboxgl.Map({
container: 'map',
zoom: 12.5,
center: [38.888, -77.01866],
center: [-77.01866, 38.888],
hash: true,
style: 'mapbox://styles/mapbox/streets-v9'
});

map.addControl(new mapboxgl.Navigation());

var querySource = new mapboxgl.GeoJSONSource({
data: { type: 'FeatureCollection', features: [] }
});
var boxSource = new mapboxgl.GeoJSONSource({
data: { type: 'FeatureCollection', features: [] }
});
var emptyFc = { type: 'FeatureCollection', features: [] }

map.on('style.load', function() {
map.addSource('queried', querySource);
map.addSource('queried', { type: 'geojson', data: emptyFc });
map.addLayer({
"id": "query",
"type": "line",
Expand All @@ -47,7 +42,7 @@
}
}, 'country-label-sm');

map.addSource('boxsource', boxSource);
map.addSource('boxsource', { type: 'geojson', data: emptyFc });
map.addLayer({
"id": "box",
"type": "fill",
Expand Down Expand Up @@ -81,28 +76,22 @@
[boxcoords[1][0], boxcoords[0][1]],
boxcoords[0]
];
var results = map.queryRenderedFeatures(box, {})
map.getSource('queried').setData({
type: 'FeatureCollection',
features: results
});

console.log('box', boxcoords);
map.queryRenderedFeatures(box, {
includeGeometry: true
}, function (err, results) {
console.log('queryRenderedFeatures', box, err, results);
querySource.setData({
type: 'FeatureCollection',
features: results
});

boxSource.setData({
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: boxcoords
}
}]
});
map.getSource('boxsource').setData({
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: boxcoords
}
}]
});
}
});
Expand Down
1 change: 0 additions & 1 deletion debug/random.geojson

This file was deleted.

10 changes: 0 additions & 10 deletions debug/route.json

This file was deleted.

13 changes: 5 additions & 8 deletions docs/_posts/examples/3400-01-10-live-geojson.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@
});

var url = 'https://wanderdrone.appspot.com/';
var source = new mapboxgl.GeoJSONSource({
data: url
});
window.setInterval(function() {
source.setData(url);
}, 2000);

map.on('load', function () {
map.addSource('drone', source);
window.setInterval(function() {
map.getSource('drone').setData(url);
}, 2000);

map.addSource('drone', { type: 'geojson', data: url });
map.addLayer({
"id": "drone",
"type": "symbol",
Expand Down
Loading

0 comments on commit def9cb5

Please sign in to comment.