diff --git a/examples/mapbox-vector-tiles-simple.css b/examples/mapbox-vector-tiles-advanced.css similarity index 100% rename from examples/mapbox-vector-tiles-simple.css rename to examples/mapbox-vector-tiles-advanced.css diff --git a/examples/mapbox-vector-tiles-advanced.html b/examples/mapbox-vector-tiles-advanced.html new file mode 100644 index 0000000000..0edbe9fe50 --- /dev/null +++ b/examples/mapbox-vector-tiles-advanced.html @@ -0,0 +1,17 @@ +--- +template: example.html +title: Advanced Mapbox vector tiles example +shortdesc: Example of a Mapbox vector tiles map with custom tile grid. +docs: > + A vector tiles map which reuses the same tiles for subsequent zoom levels to save bandwith on mobile devices. **Note**: No map will be visible when the access token has expired. +tags: "mapbox, vector, tiles, mobile" +resources: + - resources/mapbox-streets-v6-style.js +cloak: + pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg: Your Mapbox access token from http://mapbox.com/ here +--- +
+
+
+
+
diff --git a/examples/mapbox-vector-tiles-advanced.js b/examples/mapbox-vector-tiles-advanced.js new file mode 100644 index 0000000000..aaa0736fcc --- /dev/null +++ b/examples/mapbox-vector-tiles-advanced.js @@ -0,0 +1,73 @@ +goog.require('ol.Attribution'); +goog.require('ol.Map'); +goog.require('ol.View'); +goog.require('ol.format.MVT'); +goog.require('ol.layer.VectorTile'); +goog.require('ol.proj'); +goog.require('ol.source.VectorTile'); +goog.require('ol.style.Fill'); +goog.require('ol.style.Icon'); +goog.require('ol.style.Stroke'); +goog.require('ol.style.Style'); +goog.require('ol.style.Text'); +goog.require('ol.tilegrid.TileGrid'); + + +var key = 'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg'; + +// For how many zoom levels do we want to use the same vector tiles? +// 1 means "use tiles from all zoom levels". 2 means "use the same tiles for 2 +// subsequent zoom levels". +var reuseZoomLevels = 2; + +// Offset of loaded tiles from web mercator zoom level 0. +// 0 means "At map zoom level 0, use tiles from zoom level 0". 1 means "At map +// zoom level 0, use tiles from zoom level 1". +var zoomOffset = 1; + +// Calculation of tile urls +var resolutions = []; +for (var z = zoomOffset / reuseZoomLevels; z <= 22 / reuseZoomLevels; ++z) { + resolutions.push(156543.03392804097 / Math.pow(2, z * reuseZoomLevels)); +} +function tileUrlFunction(tileCoord) { + return ('http://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' + + '{z}/{x}/{y}.vector.pbf?access_token=' + key) + .replace('{z}', String(tileCoord[0] * reuseZoomLevels + zoomOffset)) + .replace('{x}', String(tileCoord[1])) + .replace('{y}', String(-tileCoord[2] - 1)) + .replace('{a-d}', 'abcd'.substr( + ((tileCoord[1] << tileCoord[0]) + tileCoord[2]) % 4, 1)); +} + +var map = new ol.Map({ + layers: [ + new ol.layer.VectorTile({ + preload: Infinity, + source: new ol.source.VectorTile({ + attributions: [new ol.Attribution({ + html: '© Mapbox ' + + '© ' + + 'OpenStreetMap contributors' + })], + format: new ol.format.MVT(), + tileGrid: new ol.tilegrid.TileGrid({ + extent: ol.proj.get('EPSG:3857').getExtent(), + resolutions: resolutions + }), + tilePixelRatio: 16, + tileUrlFunction: tileUrlFunction + }), + style: createMapboxStreetsV6Style() + }) + ], + target: 'map', + view: new ol.View({ + center: [0, 0], + minZoom: 1, + zoom: 2 + }) +}); + +// ol.style.Fill, ol.style.Icon, ol.style.Stroke, ol.style.Style and +// ol.style.Text are required for createMapboxStreetsV6Style() diff --git a/examples/mapbox-vector-tiles-simple.html b/examples/mapbox-vector-tiles-simple.html deleted file mode 100644 index 9a9d32764a..0000000000 --- a/examples/mapbox-vector-tiles-simple.html +++ /dev/null @@ -1,17 +0,0 @@ ---- -template: example.html -title: Simple Mapbox vector tiles example -shortdesc: Example of a simple Mapbox vector tiles map. -docs: > - A simple vector tiles map. **Note**: Make sure to get your own Mapbox API key when using this example. No map will be visible when the API key has expired. -tags: "simple, mapbox, vector, tiles" -resources: - - resources/mapbox-streets-v6-style.js -cloak: - pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg: Your Mapbox access token from http://mapbox.com/ here ---- -
-
-
-
-
diff --git a/examples/mapbox-vector-tiles-simple.js b/examples/mapbox-vector-tiles-simple.js deleted file mode 100644 index 783e2462af..0000000000 --- a/examples/mapbox-vector-tiles-simple.js +++ /dev/null @@ -1,42 +0,0 @@ -goog.require('ol.Attribution'); -goog.require('ol.Map'); -goog.require('ol.View'); -goog.require('ol.format.MVT'); -goog.require('ol.layer.VectorTile'); -goog.require('ol.source.VectorTile'); -goog.require('ol.style.Fill'); -goog.require('ol.style.Icon'); -goog.require('ol.style.Stroke'); -goog.require('ol.style.Style'); -goog.require('ol.style.Text'); - - -var key = 'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg'; - -var map = new ol.Map({ - layers: [ - new ol.layer.VectorTile({ - source: new ol.source.VectorTile({ - attributions: [new ol.Attribution({ - html: '© Mapbox ' + - '© ' + - 'OpenStreetMap contributors' - })], - format: new ol.format.MVT(), - tileGrid: ol.tilegrid.createXYZ({maxZoom: 22}), - tilePixelRatio: 16, - url: 'http://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' + - '{z}/{x}/{y}.vector.pbf?access_token=' + key - }), - style: createMapboxStreetsV6Style() - }) - ], - target: 'map', - view: new ol.View({ - center: [0, 0], - zoom: 2 - }) -}); - -// ol.style.Fill, ol.style.Icon, ol.style.Stroke, ol.style.Style and -// ol.style.Text are required for createMapboxStreetsV6Style() diff --git a/examples/mapbox-vector-tiles.html b/examples/mapbox-vector-tiles.html index 12aa0017fc..27a8dc54c2 100644 --- a/examples/mapbox-vector-tiles.html +++ b/examples/mapbox-vector-tiles.html @@ -3,7 +3,7 @@ template: example.html title: Mapbox vector tiles example shortdesc: Example of a Mapbox vector tiles map. docs: > - A vector tiles map which reuses the same tiles for subsequent zoom levels to save bandwith on mobile devices. **Note**: No map will be visible when the access token has expired. + A simple vector tiles map. **Note**: Make sure to get your own Mapbox API key when using this example. No map will be visible when the API key has expired. tags: "simple, mapbox, vector, tiles" resources: - resources/mapbox-streets-v6-style.js diff --git a/examples/mapbox-vector-tiles.js b/examples/mapbox-vector-tiles.js index aaa0736fcc..783e2462af 100644 --- a/examples/mapbox-vector-tiles.js +++ b/examples/mapbox-vector-tiles.js @@ -3,47 +3,19 @@ goog.require('ol.Map'); goog.require('ol.View'); goog.require('ol.format.MVT'); goog.require('ol.layer.VectorTile'); -goog.require('ol.proj'); goog.require('ol.source.VectorTile'); goog.require('ol.style.Fill'); goog.require('ol.style.Icon'); goog.require('ol.style.Stroke'); goog.require('ol.style.Style'); goog.require('ol.style.Text'); -goog.require('ol.tilegrid.TileGrid'); var key = 'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg'; -// For how many zoom levels do we want to use the same vector tiles? -// 1 means "use tiles from all zoom levels". 2 means "use the same tiles for 2 -// subsequent zoom levels". -var reuseZoomLevels = 2; - -// Offset of loaded tiles from web mercator zoom level 0. -// 0 means "At map zoom level 0, use tiles from zoom level 0". 1 means "At map -// zoom level 0, use tiles from zoom level 1". -var zoomOffset = 1; - -// Calculation of tile urls -var resolutions = []; -for (var z = zoomOffset / reuseZoomLevels; z <= 22 / reuseZoomLevels; ++z) { - resolutions.push(156543.03392804097 / Math.pow(2, z * reuseZoomLevels)); -} -function tileUrlFunction(tileCoord) { - return ('http://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' + - '{z}/{x}/{y}.vector.pbf?access_token=' + key) - .replace('{z}', String(tileCoord[0] * reuseZoomLevels + zoomOffset)) - .replace('{x}', String(tileCoord[1])) - .replace('{y}', String(-tileCoord[2] - 1)) - .replace('{a-d}', 'abcd'.substr( - ((tileCoord[1] << tileCoord[0]) + tileCoord[2]) % 4, 1)); -} - var map = new ol.Map({ layers: [ new ol.layer.VectorTile({ - preload: Infinity, source: new ol.source.VectorTile({ attributions: [new ol.Attribution({ html: '© Mapbox ' + @@ -51,12 +23,10 @@ var map = new ol.Map({ 'OpenStreetMap contributors' })], format: new ol.format.MVT(), - tileGrid: new ol.tilegrid.TileGrid({ - extent: ol.proj.get('EPSG:3857').getExtent(), - resolutions: resolutions - }), + tileGrid: ol.tilegrid.createXYZ({maxZoom: 22}), tilePixelRatio: 16, - tileUrlFunction: tileUrlFunction + url: 'http://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' + + '{z}/{x}/{y}.vector.pbf?access_token=' + key }), style: createMapboxStreetsV6Style() }) @@ -64,7 +34,6 @@ var map = new ol.Map({ target: 'map', view: new ol.View({ center: [0, 0], - minZoom: 1, zoom: 2 }) }); diff --git a/externs/olx.js b/externs/olx.js index 51936fde18..36d2bd800e 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -3651,12 +3651,13 @@ olx.layer.VectorOptions.prototype.visible; /** - * @typedef {{map: (ol.Map|undefined), + * @typedef {{extent: (ol.Extent|undefined), + * map: (ol.Map|undefined), * minResolution: (number|undefined), * maxResolution: (number|undefined), * opacity: (number|undefined), * renderBuffer: (number|undefined), - * renderOrder: (function(ol.Feature, ol.Feature):number|null|undefined), + * renderOrder: (function(ol.Feature, ol.Feature):number|undefined), * source: (ol.source.VectorTile|undefined), * style: (ol.style.Style|Array.|ol.style.StyleFunction|undefined), * updateWhileAnimating: (boolean|undefined), @@ -3680,9 +3681,8 @@ olx.layer.VectorTileOptions.prototype.renderBuffer; /** * Render order. Function to be used when sorting features before rendering. By - * default features are drawn in the order that they are created. Use `null` to - * avoid the sort, but get an undefined draw order. - * @type {function(ol.Feature, ol.Feature):number|null|undefined} + * default features are drawn in the order that they are created. + * @type {function(ol.Feature, ol.Feature):number|undefined} * @api */ olx.layer.VectorTileOptions.prototype.renderOrder; @@ -3703,7 +3703,7 @@ olx.layer.VectorTileOptions.prototype.map; * The bounding extent for layer rendering. The layer will not be rendered * outside of this extent. * @type {ol.Extent|undefined} - * @api + * @api stable */ olx.layer.VectorTileOptions.prototype.extent; @@ -3711,7 +3711,7 @@ olx.layer.VectorTileOptions.prototype.extent; /** * The minimum resolution (inclusive) at which this layer will be visible. * @type {number|undefined} - * @api + * @api stable */ olx.layer.VectorTileOptions.prototype.minResolution; @@ -3719,7 +3719,7 @@ olx.layer.VectorTileOptions.prototype.minResolution; /** * The maximum resolution (exclusive) below which this layer will be visible. * @type {number|undefined} - * @api + * @api stable */ olx.layer.VectorTileOptions.prototype.maxResolution; @@ -3727,15 +3727,15 @@ olx.layer.VectorTileOptions.prototype.maxResolution; /** * Opacity. 0-1. Default is `1`. * @type {number|undefined} - * @api + * @api stable */ olx.layer.VectorTileOptions.prototype.opacity; /** * Source. - * @type {ol.source.VectorTile} - * @api + * @type {ol.source.VectorTile|undefined} + * @api stable */ olx.layer.VectorTileOptions.prototype.source; @@ -3744,7 +3744,7 @@ olx.layer.VectorTileOptions.prototype.source; * Layer style. See {@link ol.style} for default style which will be used if * this is not defined. * @type {ol.style.Style|Array.|ol.style.StyleFunction|undefined} - * @api + * @api stable */ olx.layer.VectorTileOptions.prototype.style; @@ -4154,6 +4154,7 @@ olx.source.VectorTileOptions.prototype.attributions; * Feature format for tiles. Used and required by the default * `tileLoadFunction`. * @type {ol.format.Feature|undefined} + * @api */ olx.source.VectorTileOptions.prototype.format; diff --git a/src/ol/featureloader.js b/src/ol/featureloader.js index 34ceaa55fc..f3659a8dc7 100644 --- a/src/ol/featureloader.js +++ b/src/ol/featureloader.js @@ -102,7 +102,7 @@ ol.featureloader.loadFeaturesXhr = function(url, format, success, failure) { if (source) { var features = format.readFeatures(source, {featureProjection: projection}); - if (success.length == 2) { + if (ol.ENABLE_VECTOR_TILE && success.length == 2) { success.call(this, features, format.readProjection(source)); } else { success.call(this, features); @@ -171,5 +171,5 @@ ol.featureloader.xhr = function(url, format) { */ function(features) { this.addFeatures(features); - }, ol.nullFunction); + }, /* FIXME handle error */ ol.nullFunction); }; diff --git a/src/ol/format/mvtformat.js b/src/ol/format/mvtformat.js index 65d3806aaf..10c3c0e0b7 100644 --- a/src/ol/format/mvtformat.js +++ b/src/ol/format/mvtformat.js @@ -107,7 +107,7 @@ ol.format.MVT.prototype.readFeature_ = function( goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); values[this.geometryName_] = geometry; } - feature.setProperties(rawFeature.properties); + feature.setProperties(values); feature.setGeometryName(this.geometryName_); return feature; }; @@ -121,21 +121,9 @@ ol.format.MVT.prototype.readFeature_ = function( */ ol.format.MVT.prototype.readRenderFeature_ = function(rawFeature, layer) { var coords = rawFeature.loadGeometry(); - var end = 0; var ends = []; var flatCoordinates = []; - var line, coord; - for (var i = 0, ii = coords.length; i < ii; ++i) { - line = coords[i]; - for (var j = 0, jj = line.length; j < jj; ++j) { - coord = line[j]; - // Non-tilespace coords can be calculated here when a TileGrid and - // TileCoord are known. - flatCoordinates.push(coord.x, coord.y); - } - end += 2 * j; - ends.push(end); - } + ol.format.MVT.calculateFlatCoordinates_(coords, flatCoordinates, ends); var type = rawFeature.type; /** @type {ol.geom.GeometryType} */ @@ -149,15 +137,14 @@ ol.format.MVT.prototype.readRenderFeature_ = function(rawFeature, layer) { } else { geometryType = ol.geom.GeometryType.MULTI_LINE_STRING; } - } else { + } else if (type === 3) { geometryType = ol.geom.GeometryType.POLYGON; } - var properties = rawFeature.properties; - properties[this.layerName_] = layer; + var values = rawFeature.properties; + values[this.layerName_] = layer; - return new this.featureClass_( - geometryType, flatCoordinates, ends, rawFeature.properties); + return new this.featureClass_(geometryType, flatCoordinates, ends, values); }; @@ -180,7 +167,7 @@ ol.format.MVT.prototype.readFeatures = function(source, opt_options) { } layer = tile.layers[name]; - for (var i = 0, ii = layer.length; i < layer.length; ++i) { + for (var i = 0, ii = layer.length; i < ii; ++i) { if (featureClass === ol.render.Feature) { feature = this.readRenderFeature_(layer.feature(i), name); } else { @@ -214,20 +201,14 @@ ol.format.MVT.prototype.setLayers = function(layers) { /** * @private - * @param {Object} rawFeature Raw Mapbox feature. - * @return {ol.geom.Geometry} Geometry. + * @param {Object} coords Raw feature coordinates. + * @param {Array.} flatCoordinates Flat coordinates to be populated by + * this function. + * @param {Array.} ends Ends to be populated by this function. */ -ol.format.MVT.readGeometry_ = function(rawFeature) { - var type = rawFeature.type; - if (type === 0) { - return null; - } - - var coords = rawFeature.loadGeometry(); - +ol.format.MVT.calculateFlatCoordinates_ = function( + coords, flatCoordinates, ends) { var end = 0; - var ends = []; - var flatCoordinates = []; var line, coord; for (var i = 0, ii = coords.length; i < ii; ++i) { line = coords[i]; @@ -240,6 +221,24 @@ ol.format.MVT.readGeometry_ = function(rawFeature) { end += 2 * j; ends.push(end); } +}; + + +/** + * @private + * @param {Object} rawFeature Raw Mapbox feature. + * @return {ol.geom.Geometry} Geometry. + */ +ol.format.MVT.readGeometry_ = function(rawFeature) { + var type = rawFeature.type; + if (type === 0) { + return null; + } + + var coords = rawFeature.loadGeometry(); + var ends = []; + var flatCoordinates = []; + ol.format.MVT.calculateFlatCoordinates_(coords, flatCoordinates, ends); var geom; if (type === 1) { @@ -251,7 +250,7 @@ ol.format.MVT.readGeometry_ = function(rawFeature) { } else { geom = new ol.geom.MultiLineString(null); } - } else { + } else if (type === 3) { geom = new ol.geom.Polygon(null); } diff --git a/src/ol/geom/geometry.js b/src/ol/geom/geometry.js index 46f69d9115..a87cb6b853 100644 --- a/src/ol/geom/geometry.js +++ b/src/ol/geom/geometry.js @@ -253,7 +253,8 @@ ol.geom.Geometry.prototype.translate = goog.abstractMethod; */ ol.geom.Geometry.prototype.transform = function(source, destination) { goog.asserts.assert( - ol.proj.get(source).getUnits() !== ol.proj.Units.TILE_PIXELS, + ol.proj.get(source).getUnits() !== ol.proj.Units.TILE_PIXELS && + ol.proj.get(destination).getUnits() !== ol.proj.Units.TILE_PIXELS, 'cannot transform geometries with TILE_PIXELS units'); this.applyTransform(ol.proj.getTransform(source, destination)); return this; diff --git a/src/ol/proj/proj.js b/src/ol/proj/proj.js index 499fb5eb0e..88e95593f8 100644 --- a/src/ol/proj/proj.js +++ b/src/ol/proj/proj.js @@ -677,11 +677,8 @@ ol.proj.get = function(projectionLike) { ol.proj.equivalent = function(projection1, projection2) { if (projection1 === projection2) { return true; - } else if (projection1.getCode() === projection2.getCode() && - projection1.getUnits() === projection2.getUnits()) { - return true; - } else if (projection1.getUnits() != projection2.getUnits()) { - return false; + } else if (projection1.getCode() === projection2.getCode()) { + return projection1.getUnits() === projection2.getUnits(); } else { var transformFn = ol.proj.getTransformFromProjections( projection1, projection2); diff --git a/src/ol/render/canvas/canvasreplay.js b/src/ol/render/canvas/canvasreplay.js index 9221527e11..a31a8c9203 100644 --- a/src/ol/render/canvas/canvasreplay.js +++ b/src/ol/render/canvas/canvasreplay.js @@ -1180,6 +1180,10 @@ ol.render.canvas.PolygonReplay = function(tolerance, maxExtent, resolution) { miterLimit: undefined }; + /** + * @private + * @type {boolean} + */ this.rightHanded_ = false; }; diff --git a/src/ol/render/renderfeature.js b/src/ol/render/renderfeature.js index 7b6001ae8c..17ead76116 100644 --- a/src/ol/render/renderfeature.js +++ b/src/ol/render/renderfeature.js @@ -86,7 +86,7 @@ ol.render.Feature.prototype.getEnds = function() { * @api */ ol.render.Feature.prototype.getExtent = function() { - if (!goog.isDef(this.extent_)) { + if (!this.extent_) { this.extent_ = this.type_ === ol.geom.GeometryType.POINT ? ol.extent.createOrUpdateFromCoordinate(this.flatCoordinates_) : ol.extent.createOrUpdateFromFlatCoordinates( diff --git a/src/ol/renderer/canvas/canvasvectortilelayerrenderer.js b/src/ol/renderer/canvas/canvasvectortilelayerrenderer.js index c0d91b903d..03d9bbe8c7 100644 --- a/src/ol/renderer/canvas/canvasvectortilelayerrenderer.js +++ b/src/ol/renderer/canvas/canvasvectortilelayerrenderer.js @@ -86,7 +86,8 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame = var projection = viewState.projection; var resolution = viewState.resolution; var rotation = viewState.rotation; - var source = this.getLayer().getSource(); + var layer = this.getLayer(); + var source = layer.getSource(); goog.asserts.assertInstanceof(source, ol.source.VectorTile, 'Source is an ol.source.VectorTile'); @@ -94,7 +95,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame = this.dispatchPreComposeEvent(context, frameState, transform); - var layer = this.getLayer(); var replayContext; if (layer.hasListener(ol.render.EventType.RENDER)) { // resize and clear @@ -160,10 +160,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame = ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile, layer, pixelRatio) { var revision = layer.getRevision(); - var renderOrder = layer.getRenderOrder(); - if (renderOrder === undefined) { - renderOrder = null; - } + var renderOrder = layer.getRenderOrder() || null; var replayState = tile.getReplayState(); if (!replayState.dirty && replayState.renderedRevision == revision && diff --git a/src/ol/source/urltilesource.js b/src/ol/source/urltilesource.js index 1ed9338ccf..0f0b70b7f5 100644 --- a/src/ol/source/urltilesource.js +++ b/src/ol/source/urltilesource.js @@ -112,7 +112,7 @@ ol.source.UrlTile.prototype.getTileUrlFunction = function() { /** - * Return the URLs used for this XYZ source. + * Return the URLs used for this source. * When a tileUrlFunction is used instead of url or urls, * null will be returned. * @return {!Array.|null} URLs. diff --git a/src/ol/vectortile.js b/src/ol/vectortile.js index 29ab88587c..a533a1c92a 100644 --- a/src/ol/vectortile.js +++ b/src/ol/vectortile.js @@ -170,7 +170,7 @@ ol.VectorTile.prototype.setState = function(tileState) { /** - * Set the feeature loader for reading this tile's features. + * Set the feature loader for reading this tile's features. * @param {ol.FeatureLoader} loader Feature loader. * @api */ diff --git a/test_rendering/spec/ol/data/tiles/mvt/14-8938-5680.vector.pbf b/test_rendering/spec/ol/data/tiles/mvt/14-8938-5680.vector.pbf new file mode 100644 index 0000000000..0ed0c1ee24 Binary files /dev/null and b/test_rendering/spec/ol/data/tiles/mvt/14-8938-5680.vector.pbf differ diff --git a/test_rendering/spec/ol/layer/expected/vectortile-canvas.png b/test_rendering/spec/ol/layer/expected/vectortile-canvas.png new file mode 100644 index 0000000000..8b6ddf8536 Binary files /dev/null and b/test_rendering/spec/ol/layer/expected/vectortile-canvas.png differ diff --git a/test_rendering/spec/ol/layer/vectortile.test.js b/test_rendering/spec/ol/layer/vectortile.test.js new file mode 100644 index 0000000000..44b9eeadba --- /dev/null +++ b/test_rendering/spec/ol/layer/vectortile.test.js @@ -0,0 +1,82 @@ +goog.provide('ol.test.rendering.layer.VectorTile'); + +describe('ol.rendering.layer.VectorTile', function() { + + var target, map; + + function createMap(renderer) { + target = createMapDiv(50, 50); + + map = new ol.Map({ + target: target, + renderer: renderer, + view: new ol.View({ + center: [1825927.7316762917, 6143091.089223046], + zoom: 14 + }) + }); + return map; + } + + function waitForTiles(source, layerOptions, onTileLoaded) { + var tilesLoading = 0; + var tileLoaded = 0; + + var update = function() { + if (tilesLoading === tileLoaded) { + onTileLoaded(); + } + }; + + source.on('tileloadstart', function(event) { + tilesLoading++; + }); + source.on('tileloadend', function(event) { + tileLoaded++; + update(); + }); + source.on('tileloaderror', function(event) { + expect().fail('Tile failed to load'); + }); + + var options = { + source: source + }; + goog.object.extend(options, layerOptions); + map.addLayer(new ol.layer.VectorTile(options)); + } + + describe('vector tile layer', function() { + var source; + + beforeEach(function() { + source = new ol.source.VectorTile({ + format: new ol.format.MVT(), + tileGrid: ol.tilegrid.createXYZ(), + tilePixelRatio: 16, + url: 'spec/ol/data/tiles/mvt/{z}-{x}-{y}.vector.pbf' + }); + }); + + afterEach(function() { + disposeMap(map); + }); + + it('renders correctly with the canvas renderer', function(done) { + map = createMap('canvas'); + waitForTiles(source, {}, function() { + expectResemble(map, 'spec/ol/layer/expected/vectortile-canvas.png', + IMAGE_TOLERANCE, done); + }); + }); + + }); + +}); + +goog.require('goog.object'); +goog.require('ol.format.MVT'); +goog.require('ol.Map'); +goog.require('ol.View'); +goog.require('ol.layer.VectorTile'); +goog.require('ol.source.VectorTile');