From d3427939df15434510a7ba980fef98a071acb0d9 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Fri, 4 Mar 2016 13:33:53 -0800 Subject: [PATCH] add synchronous version of queryRenderedFeatures --- js/source/source.js | 18 +++++++----------- js/style/style.js | 31 ++++++++++++++++++++----------- js/ui/map.js | 24 ++++++++++++++++++++---- 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/js/source/source.js b/js/source/source.js index 20b15e9c7e7..9baf2a16d6a 100644 --- a/js/source/source.js +++ b/js/source/source.js @@ -67,7 +67,7 @@ exports._getVisibleCoordinates = function() { else return this._pyramid.renderedIDs().map(TileCoord.fromID); }; -exports._queryRenderedVectorFeatures = function(queryGeometry, params, classes, zoom, bearing, callback) { +exports._queryRenderedVectorFeatures = function(resultFeatures, queryGeometry, params, classes, zoom, bearing, callback) { if (!this._pyramid) return callback(null, []); @@ -76,10 +76,10 @@ exports._queryRenderedVectorFeatures = function(queryGeometry, params, classes, return callback(null, []); var styleLayers = this.map.style._layers; - var features = []; - var async = true; - if (async) { + var isAsync = callback !== undefined; + + if (isAsync) { util.asyncAll(tilesIn, function(tileIn, callback) { if (!tileIn.tile.loaded || !tileIn.tile.featureTree) return callback(); @@ -101,18 +101,18 @@ exports._queryRenderedVectorFeatures = function(queryGeometry, params, classes, collisionTile: collisionTile.data, rawTileData: tileIn.tile.rawTileData.slice() }, function(err_, data) { - if (data) tileIn.tile.featureTree.makeGeoJSON(features, data, styleLayers); + if (data) tileIn.tile.featureTree.makeGeoJSON(resultFeatures, data, styleLayers); callback(); }, tileIn.tile.workerID); }.bind(this), function() { - callback(null, features); + callback(null); }); } else { for (var r = 0; r < tilesIn.length; r++) { var tileIn = tilesIn[r]; if (!tileIn.tile.loaded || !tileIn.tile.featureTree) continue; - tileIn.tile.featureTree.query(features, { + tileIn.tile.featureTree.query(resultFeatures, { queryGeometry: tileIn.queryGeometry, scale: tileIn.scale, tileSize: tileIn.tile.tileSize, @@ -120,10 +120,6 @@ exports._queryRenderedVectorFeatures = function(queryGeometry, params, classes, params: params }, styleLayers, true); } - - setTimeout(function() { - callback(null, features); - }, 0); } }; diff --git a/js/style/style.js b/js/style/style.js index 3727470fb4a..c7458bcd66d 100644 --- a/js/style/style.js +++ b/js/style/style.js @@ -403,24 +403,33 @@ Style.prototype = util.inherit(Evented, { }, queryRenderedFeatures: function(queryGeometry, params, classes, zoom, bearing, callback) { - var features = []; + var resultFeatures = []; var error = null; if (params.layer) { params.layerIDs = Array.isArray(params.layer) ? params.layer : [params.layer]; } - util.asyncAll(Object.keys(this.sources), function(id, callback) { - var source = this.sources[id]; - source.queryRenderedFeatures(queryGeometry, params, classes, zoom, bearing, function(err, result) { - if (result) features = features.concat(result); - if (err) error = err; - callback(); + var isAsync = callback !== undefined; + + if (isAsync) { + util.asyncAll(Object.keys(this.sources), function(id, callback) { + var source = this.sources[id]; + source.queryRenderedFeatures(resultFeatures, queryGeometry, params, classes, zoom, bearing, function(err) { + if (err) error = err; + callback(); + }); + }.bind(this), function() { + if (error) return callback(error); + callback(null, resultFeatures); }); - }.bind(this), function() { - if (error) return callback(error); - callback(null, features); - }); + } else { + for (var id in this.sources) { + this.sources[id].queryRenderedFeatures(resultFeatures, queryGeometry, params, classes, zoom, bearing); + } + + return resultFeatures; + } }, _remove: function() { diff --git a/js/ui/map.js b/js/ui/map.js index a206fe7071a..44b460be4f1 100644 --- a/js/ui/map.js +++ b/js/ui/map.js @@ -327,9 +327,27 @@ util.extend(Map.prototype, /** @lends Map.prototype */{ * }); */ queryRenderedFeatures: function(pointOrBox, params, callback) { - if (callback === undefined) { + if (!(pointOrBox instanceof Point || Array.isArray(pointOrBox))) { callback = params; params = pointOrBox; + pointOrBox = undefined; + } + var queryGeometry = this._makeQueryGeometry(pointOrBox); + this.style.queryRenderedFeatures(queryGeometry, params, this._classes, this.transform.zoom, this.transform.angle, callback); + return this; + }, + + queryRenderedFeaturesSync: function(pointOrBox, params) { + if (!(pointOrBox instanceof Point || Array.isArray(pointOrBox))) { + params = pointOrBox; + pointOrBox = undefined; + } + var queryGeometry = this._makeQueryGeometry(pointOrBox); + return this.style.queryRenderedFeatures(queryGeometry, params, this._classes, this.transform.zoom, this.transform.angle); + }, + + _makeQueryGeometry: function(pointOrBox) { + if (pointOrBox === undefined) { // bounds was omitted: use full viewport pointOrBox = [ Point.convert([0, 0]), @@ -358,11 +376,9 @@ util.extend(Map.prototype, /** @lends Map.prototype */{ return this.transform.locationCoordinate(this.transform.pointLocation(p).wrap()); }.bind(this)); - this.style.queryRenderedFeatures(queryGeometry, params, this._classes, this.transform.zoom, this.transform.angle, callback); - return this; + return queryGeometry; }, - /** * Get data from vector tiles as an array of GeoJSON Features. *