UNPKG

mapbox-gl

Version:
179 lines (147 loc) 4.83 kB
'use strict'; var util = require('../util/util'); var Evented = require('../util/evented'); var TilePyramid = require('./tile_pyramid'); var Source = require('./source'); var urlResolve = require('resolve-url'); module.exports = GeoJSONSource; /** * Create a GeoJSON data source instance given an options object * @class GeoJSONSource * @param {Object} [options] * @param {Object|string} options.data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files. * @param {number} [options.maxzoom=14] Maximum zoom to preserve detail at. * @example * var sourceObj = new mapboxgl.GeoJSONSource({ * data: { * "type": "FeatureCollection", * "features": [{ * "type": "Feature", * "geometry": { * "type": "Point", * "coordinates": [ * -76.53063297271729, * 39.18174077994108 * ] * } * }] * } * }); * map.addSource('some id', sourceObj); // add * map.removeSource('some id'); // remove */ function GeoJSONSource(options) { options = options || {}; this._data = options.data; if (options.maxzoom !== undefined) this.maxzoom = options.maxzoom; this._pyramid = new TilePyramid({ tileSize: 512, minzoom: this.minzoom, maxzoom: this.maxzoom, cacheSize: 20, load: this._loadTile.bind(this), abort: this._abortTile.bind(this), unload: this._unloadTile.bind(this), add: this._addTile.bind(this), remove: this._removeTile.bind(this) }); } GeoJSONSource.prototype = util.inherit(Evented, /** @lends GeoJSONSource.prototype */{ minzoom: 0, maxzoom: 14, _dirty: true, /** * Update source geojson data and rerender map * * @param {Object|string} data A GeoJSON data object or URL to it. The latter is preferable in case of large GeoJSON files. * @returns {GeoJSONSource} this */ setData: function(data) { this._data = data; this._dirty = true; this.fire('change'); if (this.map) this.update(this.map.transform); return this; }, onAdd: function(map) { this.map = map; }, loaded: function() { return this._loaded && this._pyramid.loaded(); }, update: function(transform) { if (this._dirty) { this._updateData(); } if (this._loaded) { this._pyramid.update(this.used, transform); } }, reload: function() { this._pyramid.reload(); }, render: Source._renderTiles, featuresAt: Source._vectorFeaturesAt, _updateData: function() { this._dirty = false; var data = this._data; if (typeof data === 'string') { data = urlResolve(window.location.href, data); } this.workerID = this.dispatcher.send('parse geojson', { data: data, tileSize: 512, source: this.id, maxZoom: this.maxzoom }, function(err) { if (err) { this.fire('error', {error: err}); return; } this._loaded = true; this._pyramid.reload(); this.fire('change'); }.bind(this)); }, _loadTile: function(tile) { var overscaling = tile.coord.z > this.maxzoom ? Math.pow(2, tile.coord.z - this.maxzoom) : 1; var params = { uid: tile.uid, coord: tile.coord, zoom: tile.coord.z, maxZoom: this.maxzoom, tileSize: 512, source: this.id, overscaling: overscaling, angle: this.map.transform.angle, pitch: this.map.transform.pitch, collisionDebug: this.map.collisionDebug }; tile.workerID = this.dispatcher.send('load geojson tile', params, function(err, data) { tile.unloadVectorData(this.map.painter); if (tile.aborted) return; if (err) { this.fire('tile.error', {tile: tile}); return; } tile.loadVectorData(data); this.fire('tile.load', {tile: tile}); }.bind(this), this.workerID); }, _abortTile: function(tile) { tile.aborted = true; }, _addTile: function(tile) { this.fire('tile.add', {tile: tile}); }, _removeTile: function(tile) { this.fire('tile.remove', {tile: tile}); }, _unloadTile: function(tile) { tile.unloadVectorData(this.map.painter); this.glyphAtlas.removeGlyphs(tile.uid); this.dispatcher.send('remove tile', { uid: tile.uid, source: this.id }, null, tile.workerID); } });