Merge pull request #6779 from ahocevar/vector-tile-grid
Decouple source and rendered tile grid of vector tile sources
This commit is contained in:
@@ -3,7 +3,7 @@ layout: example.html
|
|||||||
title: Advanced Mapbox Vector Tiles
|
title: Advanced Mapbox Vector Tiles
|
||||||
shortdesc: Example of a Mapbox vector tiles map with custom tile grid.
|
shortdesc: Example of a Mapbox vector tiles map with custom tile grid.
|
||||||
docs: >
|
docs: >
|
||||||
A vector tiles map which reuses the same tiles for subsequent zoom levels to save bandwidth on mobile devices. **Note**: No map will be visible when the access token has expired.
|
A vector tiles map which reuses the same source tiles for subsequent zoom levels to save bandwidth on mobile devices. **Note**: No map will be visible when the access token has expired.
|
||||||
tags: "mapbox, vector, tiles, mobile"
|
tags: "mapbox, vector, tiles, mobile"
|
||||||
resources:
|
resources:
|
||||||
- resources/mapbox-streets-v6-style.js
|
- resources/mapbox-streets-v6-style.js
|
||||||
|
|||||||
@@ -15,25 +15,16 @@ goog.require('ol.tilegrid.TileGrid');
|
|||||||
|
|
||||||
var key = 'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg';
|
var key = 'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg';
|
||||||
|
|
||||||
// For how many zoom levels do we want to use the same vector tiles?
|
// Calculation of resolutions that match zoom levels 1, 3, 5, 7, 9, 11, 13, 15.
|
||||||
// 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 = [];
|
var resolutions = [];
|
||||||
for (var z = zoomOffset / reuseZoomLevels; z <= 22 / reuseZoomLevels; ++z) {
|
for (var i = 0; i <= 7; ++i) {
|
||||||
resolutions.push(156543.03392804097 / Math.pow(2, z * reuseZoomLevels));
|
resolutions.push(156543.03392804097 / Math.pow(2, i * 2));
|
||||||
}
|
}
|
||||||
|
// Calculation of tile urls for zoom levels 1, 3, 5, 7, 9, 11, 13, 15.
|
||||||
function tileUrlFunction(tileCoord) {
|
function tileUrlFunction(tileCoord) {
|
||||||
return ('https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
|
return ('https://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
|
||||||
'{z}/{x}/{y}.vector.pbf?access_token=' + key)
|
'{z}/{x}/{y}.vector.pbf?access_token=' + key)
|
||||||
.replace('{z}', String(tileCoord[0] * reuseZoomLevels + zoomOffset))
|
.replace('{z}', String(tileCoord[0] * 2 - 1))
|
||||||
.replace('{x}', String(tileCoord[1]))
|
.replace('{x}', String(tileCoord[1]))
|
||||||
.replace('{y}', String(-tileCoord[2] - 1))
|
.replace('{y}', String(-tileCoord[2] - 1))
|
||||||
.replace('{a-d}', 'abcd'.substr(
|
.replace('{a-d}', 'abcd'.substr(
|
||||||
@@ -43,8 +34,6 @@ function tileUrlFunction(tileCoord) {
|
|||||||
var map = new ol.Map({
|
var map = new ol.Map({
|
||||||
layers: [
|
layers: [
|
||||||
new ol.layer.VectorTile({
|
new ol.layer.VectorTile({
|
||||||
renderMode: 'vector',
|
|
||||||
preload: Infinity,
|
|
||||||
source: new ol.source.VectorTile({
|
source: new ol.source.VectorTile({
|
||||||
attributions: '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
|
attributions: '© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> ' +
|
||||||
'© <a href="https://www.openstreetmap.org/copyright">' +
|
'© <a href="https://www.openstreetmap.org/copyright">' +
|
||||||
@@ -52,9 +41,10 @@ var map = new ol.Map({
|
|||||||
format: new ol.format.MVT(),
|
format: new ol.format.MVT(),
|
||||||
tileGrid: new ol.tilegrid.TileGrid({
|
tileGrid: new ol.tilegrid.TileGrid({
|
||||||
extent: ol.proj.get('EPSG:3857').getExtent(),
|
extent: ol.proj.get('EPSG:3857').getExtent(),
|
||||||
resolutions: resolutions
|
resolutions: resolutions,
|
||||||
|
tileSize: 512
|
||||||
}),
|
}),
|
||||||
tilePixelRatio: 16,
|
tilePixelRatio: 8,
|
||||||
tileUrlFunction: tileUrlFunction
|
tileUrlFunction: tileUrlFunction
|
||||||
}),
|
}),
|
||||||
style: createMapboxStreetsV6Style()
|
style: createMapboxStreetsV6Style()
|
||||||
|
|||||||
@@ -4877,7 +4877,7 @@ olx.source.VectorTileOptions.prototype.state;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to instantiate image tiles. Default is {@link ol.VectorTile}.
|
* Class used to instantiate vector tiles. Default is {@link ol.VectorTile}.
|
||||||
* @type {function(new: ol.VectorTile, ol.TileCoord,
|
* @type {function(new: ol.VectorTile, ol.TileCoord,
|
||||||
* ol.TileState, string, ol.format.Feature,
|
* ol.TileState, string, ol.format.Feature,
|
||||||
* ol.TileLoadFunctionType)|undefined}
|
* ol.TileLoadFunctionType)|undefined}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ ol.ImageTile.prototype.disposeInternal = function() {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the image element for this tile.
|
* Get the HTML image element for this tile (may be a Canvas, Image, or Video).
|
||||||
* @inheritDoc
|
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
ol.ImageTile.prototype.getImage = function() {
|
ol.ImageTile.prototype.getImage = function() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
goog.provide('ol.renderer.canvas.VectorTileLayer');
|
goog.provide('ol.renderer.canvas.VectorTileLayer');
|
||||||
|
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
|
goog.require('ol.TileState');
|
||||||
goog.require('ol.dom');
|
goog.require('ol.dom');
|
||||||
goog.require('ol.extent');
|
goog.require('ol.extent');
|
||||||
goog.require('ol.proj');
|
goog.require('ol.proj');
|
||||||
@@ -12,7 +13,6 @@ goog.require('ol.render.canvas.ReplayGroup');
|
|||||||
goog.require('ol.render.replay');
|
goog.require('ol.render.replay');
|
||||||
goog.require('ol.renderer.canvas.TileLayer');
|
goog.require('ol.renderer.canvas.TileLayer');
|
||||||
goog.require('ol.renderer.vector');
|
goog.require('ol.renderer.vector');
|
||||||
goog.require('ol.size');
|
|
||||||
goog.require('ol.transform');
|
goog.require('ol.transform');
|
||||||
|
|
||||||
|
|
||||||
@@ -23,6 +23,9 @@ goog.require('ol.transform');
|
|||||||
*/
|
*/
|
||||||
ol.renderer.canvas.VectorTileLayer = function(layer) {
|
ol.renderer.canvas.VectorTileLayer = function(layer) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {CanvasRenderingContext2D}
|
||||||
|
*/
|
||||||
this.context = null;
|
this.context = null;
|
||||||
|
|
||||||
ol.renderer.canvas.TileLayer.call(this, layer);
|
ol.renderer.canvas.TileLayer.call(this, layer);
|
||||||
@@ -95,12 +98,12 @@ ol.renderer.canvas.VectorTileLayer.prototype.prepareFrame = function(frameState,
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.VectorTile} tile Tile.
|
* @param {ol.VectorImageTile} tile Tile.
|
||||||
* @param {olx.FrameState} frameState Frame state.
|
* @param {olx.FrameState} frameState Frame state.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(tile,
|
ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(
|
||||||
frameState) {
|
tile, frameState) {
|
||||||
var layer = this.getLayer();
|
var layer = this.getLayer();
|
||||||
var pixelRatio = frameState.pixelRatio;
|
var pixelRatio = frameState.pixelRatio;
|
||||||
var projection = frameState.viewState.projection;
|
var projection = frameState.viewState.projection;
|
||||||
@@ -113,78 +116,88 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(tile,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
replayState.replayGroup = null;
|
for (var t = 0, tt = tile.tileKeys.length; t < tt; ++t) {
|
||||||
replayState.dirty = false;
|
var sourceTile = tile.getTile(tile.tileKeys[t]);
|
||||||
|
sourceTile.replayGroup = null;
|
||||||
|
replayState.dirty = false;
|
||||||
|
|
||||||
var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
|
var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
|
||||||
var tileGrid = source.getTileGrid();
|
var sourceTileGrid = source.getTileGrid();
|
||||||
var tileCoord = tile.tileCoord;
|
var sourceTileCoord = sourceTile.tileCoord;
|
||||||
var tileProjection = tile.getProjection();
|
var tileProjection = sourceTile.getProjection();
|
||||||
var resolution = tileGrid.getResolution(tileCoord[0]);
|
var tileGrid = source.getTileGridForProjection(projection);
|
||||||
var extent, reproject, tileResolution;
|
var resolution = tileGrid.getResolution(tile.tileCoord[0]);
|
||||||
if (tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS) {
|
var sourceTileResolution = sourceTileGrid.getResolution(sourceTile.tileCoord[0]);
|
||||||
var tilePixelRatio = tileResolution = source.getTilePixelRatio();
|
var tileExtent = tileGrid.getTileCoordExtent(tile.wrappedTileCoord);
|
||||||
var tileSize = ol.size.toSize(tileGrid.getTileSize(tileCoord[0]));
|
var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord);
|
||||||
extent = [0, 0, tileSize[0] * tilePixelRatio, tileSize[1] * tilePixelRatio];
|
var sharedExtent = ol.extent.getIntersection(tileExtent, sourceTileExtent);
|
||||||
} else {
|
var extent, reproject, tileResolution;
|
||||||
tileResolution = resolution;
|
if (tileProjection.getUnits() == ol.proj.Units.TILE_PIXELS) {
|
||||||
extent = tileGrid.getTileCoordExtent(tileCoord);
|
var tilePixelRatio = tileResolution = source.getTilePixelRatio();
|
||||||
if (!ol.proj.equivalent(projection, tileProjection)) {
|
var transform = ol.transform.compose(this.tmpTransform_,
|
||||||
reproject = true;
|
0, 0,
|
||||||
tile.setProjection(projection);
|
1 / sourceTileResolution * tilePixelRatio, -1 / sourceTileResolution * tilePixelRatio,
|
||||||
}
|
0,
|
||||||
}
|
-sourceTileExtent[0], -sourceTileExtent[3]);
|
||||||
replayState.dirty = false;
|
extent = (ol.transform.apply(transform, [sharedExtent[0], sharedExtent[3]])
|
||||||
var replayGroup = new ol.render.canvas.ReplayGroup(0, extent,
|
.concat(ol.transform.apply(transform, [sharedExtent[2], sharedExtent[1]])));
|
||||||
tileResolution, source.getOverlaps(), layer.getRenderBuffer());
|
|
||||||
var squaredTolerance = ol.renderer.vector.getSquaredTolerance(
|
|
||||||
tileResolution, pixelRatio);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
|
||||||
* @this {ol.renderer.canvas.VectorTileLayer}
|
|
||||||
*/
|
|
||||||
function renderFeature(feature) {
|
|
||||||
var styles;
|
|
||||||
var styleFunction = feature.getStyleFunction();
|
|
||||||
if (styleFunction) {
|
|
||||||
styles = styleFunction.call(/** @type {ol.Feature} */ (feature), resolution);
|
|
||||||
} else {
|
} else {
|
||||||
styleFunction = layer.getStyleFunction();
|
tileResolution = resolution;
|
||||||
|
extent = sharedExtent;
|
||||||
|
if (!ol.proj.equivalent(projection, tileProjection)) {
|
||||||
|
reproject = true;
|
||||||
|
sourceTile.setProjection(projection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
replayState.dirty = false;
|
||||||
|
var replayGroup = new ol.render.canvas.ReplayGroup(0, extent,
|
||||||
|
tileResolution, source.getOverlaps(), layer.getRenderBuffer());
|
||||||
|
var squaredTolerance = ol.renderer.vector.getSquaredTolerance(
|
||||||
|
tileResolution, pixelRatio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||||
|
* @this {ol.renderer.canvas.VectorTileLayer}
|
||||||
|
*/
|
||||||
|
var renderFeature = function(feature) {
|
||||||
|
var styles;
|
||||||
|
var styleFunction = feature.getStyleFunction();
|
||||||
if (styleFunction) {
|
if (styleFunction) {
|
||||||
styles = styleFunction(feature, resolution);
|
styles = styleFunction.call(/** @type {ol.Feature} */ (feature), resolution);
|
||||||
|
} else {
|
||||||
|
styleFunction = layer.getStyleFunction();
|
||||||
|
if (styleFunction) {
|
||||||
|
styles = styleFunction(feature, resolution);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (styles) {
|
||||||
if (styles) {
|
if (!Array.isArray(styles)) {
|
||||||
if (!Array.isArray(styles)) {
|
styles = [styles];
|
||||||
styles = [styles];
|
}
|
||||||
|
var dirty = this.renderFeature(feature, squaredTolerance, styles,
|
||||||
|
replayGroup);
|
||||||
|
this.dirty_ = this.dirty_ || dirty;
|
||||||
|
replayState.dirty = replayState.dirty || dirty;
|
||||||
}
|
}
|
||||||
var dirty = this.renderFeature(feature, squaredTolerance, styles,
|
};
|
||||||
replayGroup);
|
|
||||||
this.dirty_ = this.dirty_ || dirty;
|
var features = sourceTile.getFeatures();
|
||||||
replayState.dirty = replayState.dirty || dirty;
|
if (renderOrder && renderOrder !== replayState.renderedRenderOrder) {
|
||||||
|
features.sort(renderOrder);
|
||||||
}
|
}
|
||||||
}
|
var feature;
|
||||||
|
for (var i = 0, ii = features.length; i < ii; ++i) {
|
||||||
var features = tile.getFeatures();
|
feature = features[i];
|
||||||
if (renderOrder && renderOrder !== replayState.renderedRenderOrder) {
|
if (reproject) {
|
||||||
features.sort(renderOrder);
|
feature.getGeometry().transform(tileProjection, projection);
|
||||||
}
|
}
|
||||||
var feature;
|
renderFeature.call(this, feature);
|
||||||
for (var i = 0, ii = features.length; i < ii; ++i) {
|
|
||||||
feature = features[i];
|
|
||||||
if (reproject) {
|
|
||||||
feature.getGeometry().transform(tileProjection, projection);
|
|
||||||
}
|
}
|
||||||
renderFeature.call(this, feature);
|
replayGroup.finish();
|
||||||
|
sourceTile.setReplayGroup(tile.tileCoord.toString(), replayGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
replayGroup.finish();
|
|
||||||
|
|
||||||
replayState.renderedRevision = revision;
|
replayState.renderedRevision = revision;
|
||||||
replayState.renderedRenderOrder = renderOrder;
|
replayState.renderedRenderOrder = renderOrder;
|
||||||
replayState.replayGroup = replayGroup;
|
|
||||||
replayState.resolution = NaN;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -193,10 +206,10 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup_ = function(tile,
|
|||||||
*/
|
*/
|
||||||
ol.renderer.canvas.VectorTileLayer.prototype.drawTileImage = function(
|
ol.renderer.canvas.VectorTileLayer.prototype.drawTileImage = function(
|
||||||
tile, frameState, layerState, x, y, w, h, gutter) {
|
tile, frameState, layerState, x, y, w, h, gutter) {
|
||||||
var vectorTile = /** @type {ol.VectorTile} */ (tile);
|
var vectorImageTile = /** @type {ol.VectorImageTile} */ (tile);
|
||||||
this.createReplayGroup_(vectorTile, frameState);
|
this.createReplayGroup_(vectorImageTile, frameState);
|
||||||
if (this.context) {
|
if (this.context) {
|
||||||
this.renderTileImage_(vectorTile, frameState, layerState);
|
this.renderTileImage_(vectorImageTile, frameState, layerState);
|
||||||
ol.renderer.canvas.TileLayer.prototype.drawTileImage.apply(this, arguments);
|
ol.renderer.canvas.TileLayer.prototype.drawTileImage.apply(this, arguments);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -213,54 +226,61 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
|
|||||||
/** @type {Object.<string, boolean>} */
|
/** @type {Object.<string, boolean>} */
|
||||||
var features = {};
|
var features = {};
|
||||||
|
|
||||||
/** @type {Array.<ol.VectorTile>} */
|
/** @type {Array.<ol.VectorImageTile>} */
|
||||||
var replayables = this.renderedTiles;
|
var renderedTiles = this.renderedTiles;
|
||||||
|
|
||||||
var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
|
var source = /** @type {ol.source.VectorTile} */ (layer.getSource());
|
||||||
var tileGrid = source.getTileGrid();
|
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
||||||
var found, tileSpaceCoordinate;
|
var sourceTileGrid = source.getTileGrid();
|
||||||
|
var bufferedExtent, found, tileSpaceCoordinate;
|
||||||
var i, ii, origin, replayGroup;
|
var i, ii, origin, replayGroup;
|
||||||
var tile, tileCoord, tileExtent, tilePixelRatio, tileResolution;
|
var tile, tileCoord, tileExtent, tilePixelRatio, tileResolution;
|
||||||
for (i = 0, ii = replayables.length; i < ii; ++i) {
|
for (i = 0, ii = renderedTiles.length; i < ii; ++i) {
|
||||||
tile = replayables[i];
|
tile = renderedTiles[i];
|
||||||
tileCoord = tile.tileCoord;
|
tileCoord = tile.tileCoord;
|
||||||
tileExtent = source.getTileGrid().getTileCoordExtent(tileCoord, this.tmpExtent);
|
tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
|
||||||
if (!ol.extent.containsCoordinate(ol.extent.buffer(tileExtent, hitTolerance * resolution), coordinate)) {
|
bufferedExtent = ol.extent.buffer(tileExtent, hitTolerance * resolution, bufferedExtent);
|
||||||
|
if (!ol.extent.containsCoordinate(bufferedExtent, coordinate)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (tile.getProjection().getUnits() === ol.proj.Units.TILE_PIXELS) {
|
for (var t = 0, tt = tile.tileKeys.length; t < tt; ++t) {
|
||||||
origin = ol.extent.getTopLeft(tileExtent);
|
var sourceTile = tile.getTile(tile.tileKeys[t]);
|
||||||
tilePixelRatio = source.getTilePixelRatio();
|
if (sourceTile.getProjection().getUnits() === ol.proj.Units.TILE_PIXELS) {
|
||||||
tileResolution = tileGrid.getResolution(tileCoord[0]) / tilePixelRatio;
|
var sourceTileCoord = sourceTile.tileCoord;
|
||||||
tileSpaceCoordinate = [
|
var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord, this.tmpExtent);
|
||||||
(coordinate[0] - origin[0]) / tileResolution,
|
origin = ol.extent.getTopLeft(sourceTileExtent);
|
||||||
(origin[1] - coordinate[1]) / tileResolution
|
tilePixelRatio = source.getTilePixelRatio();
|
||||||
];
|
tileResolution = sourceTileGrid.getResolution(sourceTileCoord[0]) / tilePixelRatio;
|
||||||
resolution = tilePixelRatio;
|
tileSpaceCoordinate = [
|
||||||
} else {
|
(coordinate[0] - origin[0]) / tileResolution,
|
||||||
tileSpaceCoordinate = coordinate;
|
(origin[1] - coordinate[1]) / tileResolution
|
||||||
|
];
|
||||||
|
resolution = tilePixelRatio;
|
||||||
|
} else {
|
||||||
|
tileSpaceCoordinate = coordinate;
|
||||||
|
}
|
||||||
|
replayGroup = sourceTile.getReplayGroup(tile.tileCoord);
|
||||||
|
found = found || replayGroup.forEachFeatureAtCoordinate(
|
||||||
|
tileSpaceCoordinate, resolution, rotation, hitTolerance, {},
|
||||||
|
/**
|
||||||
|
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||||
|
* @return {?} Callback result.
|
||||||
|
*/
|
||||||
|
function(feature) {
|
||||||
|
var key = ol.getUid(feature).toString();
|
||||||
|
if (!(key in features)) {
|
||||||
|
features[key] = true;
|
||||||
|
return callback.call(thisArg, feature, layer);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
replayGroup = tile.getReplayState().replayGroup;
|
|
||||||
found = found || replayGroup.forEachFeatureAtCoordinate(
|
|
||||||
tileSpaceCoordinate, resolution, rotation, hitTolerance, {},
|
|
||||||
/**
|
|
||||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
|
||||||
* @return {?} Callback result.
|
|
||||||
*/
|
|
||||||
function(feature) {
|
|
||||||
var key = ol.getUid(feature).toString();
|
|
||||||
if (!(key in features)) {
|
|
||||||
features[key] = true;
|
|
||||||
return callback.call(thisArg, feature, layer);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.Tile} tile Tile.
|
* @param {ol.VectorTile} tile Tile.
|
||||||
* @param {olx.FrameState} frameState Frame state.
|
* @param {olx.FrameState} frameState Frame state.
|
||||||
* @return {ol.Transform} transform Transform.
|
* @return {ol.Transform} transform Transform.
|
||||||
* @private
|
* @private
|
||||||
@@ -308,7 +328,9 @@ ol.renderer.canvas.VectorTileLayer.prototype.handleStyleImageChange_ = function(
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, frameState, layerState) {
|
ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, frameState, layerState) {
|
||||||
var renderMode = this.getLayer().getRenderMode();
|
var layer = this.getLayer();
|
||||||
|
var source = layer.getSource();
|
||||||
|
var renderMode = layer.getRenderMode();
|
||||||
var replays = ol.renderer.canvas.VectorTileLayer.VECTOR_REPLAYS[renderMode];
|
var replays = ol.renderer.canvas.VectorTileLayer.VECTOR_REPLAYS[renderMode];
|
||||||
if (replays) {
|
if (replays) {
|
||||||
var pixelRatio = frameState.pixelRatio;
|
var pixelRatio = frameState.pixelRatio;
|
||||||
@@ -317,40 +339,54 @@ ol.renderer.canvas.VectorTileLayer.prototype.postCompose = function(context, fra
|
|||||||
var offsetX = Math.round(pixelRatio * size[0] / 2);
|
var offsetX = Math.round(pixelRatio * size[0] / 2);
|
||||||
var offsetY = Math.round(pixelRatio * size[1] / 2);
|
var offsetY = Math.round(pixelRatio * size[1] / 2);
|
||||||
var tiles = this.renderedTiles;
|
var tiles = this.renderedTiles;
|
||||||
|
var tilePixelRatio = layer.getSource().getTilePixelRatio();
|
||||||
|
var sourceTileGrid = source.getTileGrid();
|
||||||
|
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
||||||
var clips = [];
|
var clips = [];
|
||||||
var zs = [];
|
var zs = [];
|
||||||
for (var i = tiles.length - 1; i >= 0; --i) {
|
for (var i = tiles.length - 1; i >= 0; --i) {
|
||||||
var tile = /** @type {ol.VectorTile} */ (tiles[i]);
|
var tile = /** @type {ol.VectorImageTile} */ (tiles[i]);
|
||||||
// Create a clip mask for regions in this low resolution tile that are
|
if (tile.getState() == ol.TileState.ABORT) {
|
||||||
// already filled by a higher resolution tile
|
continue;
|
||||||
var transform = this.getReplayTransform_(tile, frameState);
|
}
|
||||||
var currentClip = tile.getReplayState().replayGroup.getClipCoords(transform);
|
var tileCoord = tile.tileCoord;
|
||||||
var currentZ = tile.tileCoord[0];
|
var worldOffset = tileGrid.getTileCoordExtent(tileCoord)[0] -
|
||||||
context.save();
|
tileGrid.getTileCoordExtent(tile.wrappedTileCoord)[0];
|
||||||
context.globalAlpha = layerState.opacity;
|
for (var t = 0, tt = tile.tileKeys.length; t < tt; ++t) {
|
||||||
ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
|
var sourceTile = tile.getTile(tile.tileKeys[t]);
|
||||||
for (var j = 0, jj = clips.length; j < jj; ++j) {
|
var currentZ = sourceTile.tileCoord[0];
|
||||||
var clip = clips[j];
|
var sourceResolution = sourceTileGrid.getResolution(currentZ);
|
||||||
if (currentZ < zs[j]) {
|
var transform = this.getReplayTransform_(sourceTile, frameState);
|
||||||
context.beginPath();
|
ol.transform.translate(transform, worldOffset * tilePixelRatio / sourceResolution, 0);
|
||||||
// counter-clockwise (outer ring) for current tile
|
var replayGroup = sourceTile.getReplayGroup(tileCoord.toString());
|
||||||
context.moveTo(currentClip[0], currentClip[1]);
|
var currentClip = replayGroup.getClipCoords(transform);
|
||||||
context.lineTo(currentClip[2], currentClip[3]);
|
context.save();
|
||||||
context.lineTo(currentClip[4], currentClip[5]);
|
context.globalAlpha = layerState.opacity;
|
||||||
context.lineTo(currentClip[6], currentClip[7]);
|
ol.render.canvas.rotateAtOffset(context, -rotation, offsetX, offsetY);
|
||||||
// clockwise (inner ring) for higher resolution tile
|
// Create a clip mask for regions in this low resolution tile that are
|
||||||
context.moveTo(clip[6], clip[7]);
|
// already filled by a higher resolution tile
|
||||||
context.lineTo(clip[4], clip[5]);
|
for (var j = 0, jj = clips.length; j < jj; ++j) {
|
||||||
context.lineTo(clip[2], clip[3]);
|
var clip = clips[j];
|
||||||
context.lineTo(clip[0], clip[1]);
|
if (currentZ < zs[j]) {
|
||||||
context.clip();
|
context.beginPath();
|
||||||
}
|
// counter-clockwise (outer ring) for current tile
|
||||||
|
context.moveTo(currentClip[0], currentClip[1]);
|
||||||
|
context.lineTo(currentClip[2], currentClip[3]);
|
||||||
|
context.lineTo(currentClip[4], currentClip[5]);
|
||||||
|
context.lineTo(currentClip[6], currentClip[7]);
|
||||||
|
// clockwise (inner ring) for higher resolution tile
|
||||||
|
context.moveTo(clip[6], clip[7]);
|
||||||
|
context.lineTo(clip[4], clip[5]);
|
||||||
|
context.lineTo(clip[2], clip[3]);
|
||||||
|
context.lineTo(clip[0], clip[1]);
|
||||||
|
context.clip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
replayGroup.replay(context, pixelRatio, transform, rotation, {}, replays);
|
||||||
|
context.restore();
|
||||||
|
clips.push(currentClip);
|
||||||
|
zs.push(currentZ);
|
||||||
}
|
}
|
||||||
var replayGroup = tile.getReplayState().replayGroup;
|
|
||||||
replayGroup.replay(context, pixelRatio, transform, rotation, {}, replays);
|
|
||||||
context.restore();
|
|
||||||
clips.push(currentClip);
|
|
||||||
zs.push(currentZ);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ol.renderer.canvas.TileLayer.prototype.postCompose.apply(this, arguments);
|
ol.renderer.canvas.TileLayer.prototype.postCompose.apply(this, arguments);
|
||||||
@@ -386,7 +422,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderFeature = function(feature, s
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.VectorTile} tile Tile.
|
* @param {ol.VectorImageTile} tile Tile.
|
||||||
* @param {olx.FrameState} frameState Frame state.
|
* @param {olx.FrameState} frameState Frame state.
|
||||||
* @param {ol.LayerState} layerState Layer state.
|
* @param {ol.LayerState} layerState Layer state.
|
||||||
* @private
|
* @private
|
||||||
@@ -399,28 +435,38 @@ ol.renderer.canvas.VectorTileLayer.prototype.renderTileImage_ = function(
|
|||||||
var replays = ol.renderer.canvas.VectorTileLayer.IMAGE_REPLAYS[layer.getRenderMode()];
|
var replays = ol.renderer.canvas.VectorTileLayer.IMAGE_REPLAYS[layer.getRenderMode()];
|
||||||
if (replays && replayState.renderedTileRevision !== revision) {
|
if (replays && replayState.renderedTileRevision !== revision) {
|
||||||
replayState.renderedTileRevision = revision;
|
replayState.renderedTileRevision = revision;
|
||||||
var tileCoord = tile.tileCoord;
|
var tileCoord = tile.wrappedTileCoord;
|
||||||
var z = tile.tileCoord[0];
|
var z = tileCoord[0];
|
||||||
var pixelRatio = frameState.pixelRatio;
|
var pixelRatio = frameState.pixelRatio;
|
||||||
var source = layer.getSource();
|
var source = layer.getSource();
|
||||||
var tileGrid = source.getTileGrid();
|
var sourceTileGrid = source.getTileGrid();
|
||||||
|
var tileGrid = source.getTileGridForProjection(frameState.viewState.projection);
|
||||||
|
var resolution = tileGrid.getResolution(z);
|
||||||
var tilePixelRatio = source.getTilePixelRatio();
|
var tilePixelRatio = source.getTilePixelRatio();
|
||||||
var transform = ol.transform.reset(this.tmpTransform_);
|
|
||||||
if (tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
|
|
||||||
var renderPixelRatio = pixelRatio / tilePixelRatio;
|
|
||||||
ol.transform.scale(transform, renderPixelRatio, renderPixelRatio);
|
|
||||||
} else {
|
|
||||||
var resolution = tileGrid.getResolution(z);
|
|
||||||
var pixelScale = pixelRatio / resolution;
|
|
||||||
var tileExtent = tileGrid.getTileCoordExtent(tileCoord, this.tmpExtent);
|
|
||||||
ol.transform.scale(transform, pixelScale, -pixelScale);
|
|
||||||
ol.transform.translate(transform, -tileExtent[0], -tileExtent[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
var context = tile.getContext();
|
var context = tile.getContext();
|
||||||
var size = source.getTilePixelSize(z, pixelRatio, frameState.viewState.projection);
|
var size = source.getTilePixelSize(z, pixelRatio, frameState.viewState.projection);
|
||||||
context.canvas.width = size[0];
|
context.canvas.width = size[0];
|
||||||
context.canvas.height = size[1];
|
context.canvas.height = size[1];
|
||||||
replayState.replayGroup.replay(context, pixelRatio, transform, 0, {}, replays);
|
var tileExtent = tileGrid.getTileCoordExtent(tileCoord);
|
||||||
|
for (var i = 0, ii = tile.tileKeys.length; i < ii; ++i) {
|
||||||
|
var sourceTile = tile.getTile(tile.tileKeys[i]);
|
||||||
|
var sourceTileCoord = sourceTile.tileCoord;
|
||||||
|
var pixelScale = pixelRatio / resolution;
|
||||||
|
var transform = ol.transform.reset(this.tmpTransform_);
|
||||||
|
if (sourceTile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
|
||||||
|
var sourceTileExtent = sourceTileGrid.getTileCoordExtent(sourceTileCoord, this.tmpExtent);
|
||||||
|
var sourceResolution = sourceTileGrid.getResolution(sourceTileCoord[0]);
|
||||||
|
var renderPixelRatio = pixelRatio / tilePixelRatio * sourceResolution / resolution;
|
||||||
|
ol.transform.scale(transform, renderPixelRatio, renderPixelRatio);
|
||||||
|
var offsetX = (sourceTileExtent[0] - tileExtent[0]) / sourceResolution * tilePixelRatio;
|
||||||
|
var offsetY = (tileExtent[3] - sourceTileExtent[3]) / sourceResolution * tilePixelRatio;
|
||||||
|
ol.transform.translate(transform, Math.round(offsetX), Math.round(offsetY));
|
||||||
|
} else {
|
||||||
|
ol.transform.scale(transform, pixelScale, -pixelScale);
|
||||||
|
ol.transform.translate(transform, -tileExtent[0], -tileExtent[3]);
|
||||||
|
}
|
||||||
|
var replayGroup = sourceTile.getReplayGroup(tile.tileCoord.toString());
|
||||||
|
replayGroup.replay(context, pixelRatio, transform, 0, {}, replays);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -202,7 +202,8 @@ ol.reproj.Tile.prototype.disposeInternal = function() {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* Get the HTML Canvas element for this tile.
|
||||||
|
* @return {HTMLCanvasElement} Canvas.
|
||||||
*/
|
*/
|
||||||
ol.reproj.Tile.prototype.getImage = function() {
|
ol.reproj.Tile.prototype.getImage = function() {
|
||||||
return this.canvas_;
|
return this.canvas_;
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ ol.inherits(ol.source.TileDebug.Tile_, ol.Tile);
|
|||||||
/**
|
/**
|
||||||
* Get the image element for this tile.
|
* Get the image element for this tile.
|
||||||
* @return {HTMLCanvasElement} Image.
|
* @return {HTMLCanvasElement} Image.
|
||||||
* @override
|
|
||||||
*/
|
*/
|
||||||
ol.source.TileDebug.Tile_.prototype.getImage = function() {
|
ol.source.TileDebug.Tile_.prototype.getImage = function() {
|
||||||
if (this.canvas_) {
|
if (this.canvas_) {
|
||||||
|
|||||||
@@ -320,7 +320,6 @@ ol.inherits(ol.source.TileUTFGrid.Tile_, ol.Tile);
|
|||||||
/**
|
/**
|
||||||
* Get the image element for this tile.
|
* Get the image element for this tile.
|
||||||
* @return {Image} Image.
|
* @return {Image} Image.
|
||||||
* @override
|
|
||||||
*/
|
*/
|
||||||
ol.source.TileUTFGrid.Tile_.prototype.getImage = function() {
|
ol.source.TileUTFGrid.Tile_.prototype.getImage = function() {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ goog.provide('ol.source.VectorTile');
|
|||||||
|
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.TileState');
|
goog.require('ol.TileState');
|
||||||
|
goog.require('ol.VectorImageTile');
|
||||||
goog.require('ol.VectorTile');
|
goog.require('ol.VectorTile');
|
||||||
goog.require('ol.events');
|
goog.require('ol.events');
|
||||||
goog.require('ol.events.EventType');
|
goog.require('ol.events.EventType');
|
||||||
|
goog.require('ol.proj');
|
||||||
goog.require('ol.size');
|
goog.require('ol.size');
|
||||||
|
goog.require('ol.tilegrid');
|
||||||
goog.require('ol.source.UrlTile');
|
goog.require('ol.source.UrlTile');
|
||||||
|
|
||||||
|
|
||||||
@@ -37,7 +40,7 @@ ol.source.VectorTile = function(options) {
|
|||||||
state: options.state,
|
state: options.state,
|
||||||
tileGrid: options.tileGrid,
|
tileGrid: options.tileGrid,
|
||||||
tileLoadFunction: options.tileLoadFunction ?
|
tileLoadFunction: options.tileLoadFunction ?
|
||||||
options.tileLoadFunction : ol.VectorTile.defaultLoadFunction,
|
options.tileLoadFunction : ol.VectorImageTile.defaultLoadFunction,
|
||||||
tileUrlFunction: options.tileUrlFunction,
|
tileUrlFunction: options.tileUrlFunction,
|
||||||
tilePixelRatio: options.tilePixelRatio,
|
tilePixelRatio: options.tilePixelRatio,
|
||||||
url: options.url,
|
url: options.url,
|
||||||
@@ -51,6 +54,12 @@ ol.source.VectorTile = function(options) {
|
|||||||
*/
|
*/
|
||||||
this.format_ = options.format ? options.format : null;
|
this.format_ = options.format ? options.format : null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Object.<string,ol.VectorTile>}
|
||||||
|
*/
|
||||||
|
this.sourceTiles_ = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
@@ -64,6 +73,16 @@ ol.source.VectorTile = function(options) {
|
|||||||
*/
|
*/
|
||||||
this.tileClass = options.tileClass ? options.tileClass : ol.VectorTile;
|
this.tileClass = options.tileClass ? options.tileClass : ol.VectorTile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Object.<string,ol.tilegrid.TileGrid>}
|
||||||
|
*/
|
||||||
|
this.tileGrids_ = {};
|
||||||
|
|
||||||
|
if (!this.tileGrid) {
|
||||||
|
this.tileGrid = this.getTileGridForProjection(ol.proj.get(options.projection || 'EPSG:3857'));
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
ol.inherits(ol.source.VectorTile, ol.source.UrlTile);
|
ol.inherits(ol.source.VectorTile, ol.source.UrlTile);
|
||||||
|
|
||||||
@@ -89,11 +108,13 @@ ol.source.VectorTile.prototype.getTile = function(z, x, y, pixelRatio, projectio
|
|||||||
tileCoord, projection);
|
tileCoord, projection);
|
||||||
var tileUrl = urlTileCoord ?
|
var tileUrl = urlTileCoord ?
|
||||||
this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
|
this.tileUrlFunction(urlTileCoord, pixelRatio, projection) : undefined;
|
||||||
var tile = new this.tileClass(
|
var tile = new ol.VectorImageTile(
|
||||||
tileCoord,
|
tileCoord,
|
||||||
tileUrl !== undefined ? ol.TileState.IDLE : ol.TileState.EMPTY,
|
tileUrl !== undefined ? ol.TileState.IDLE : ol.TileState.EMPTY,
|
||||||
tileUrl !== undefined ? tileUrl : '',
|
tileUrl !== undefined ? tileUrl : '',
|
||||||
this.format_, this.tileLoadFunction);
|
this.format_, this.tileLoadFunction, urlTileCoord, this.tileUrlFunction,
|
||||||
|
this.tileGrid, this.getTileGridForProjection(projection),
|
||||||
|
this.sourceTiles_, pixelRatio, projection, this.tileClass);
|
||||||
ol.events.listen(tile, ol.events.EventType.CHANGE,
|
ol.events.listen(tile, ol.events.EventType.CHANGE,
|
||||||
this.handleTileChange, this);
|
this.handleTileChange, this);
|
||||||
|
|
||||||
@@ -103,6 +124,23 @@ ol.source.VectorTile.prototype.getTile = function(z, x, y, pixelRatio, projectio
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.source.VectorTile.prototype.getTileGridForProjection = function(projection) {
|
||||||
|
var code = projection.getCode();
|
||||||
|
var tileGrid = this.tileGrids_[code];
|
||||||
|
if (!tileGrid) {
|
||||||
|
// A tile grid that matches the tile size of the source tile grid is more
|
||||||
|
// likely to have 1:1 relationships between source tiles and rendered tiles.
|
||||||
|
var sourceTileGrid = this.tileGrid;
|
||||||
|
tileGrid = this.tileGrids_[code] = ol.tilegrid.createForProjection(projection, undefined,
|
||||||
|
sourceTileGrid ? sourceTileGrid.getTileSize(sourceTileGrid.getMinZoom()) : undefined);
|
||||||
|
}
|
||||||
|
return tileGrid;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@@ -117,6 +155,6 @@ ol.source.VectorTile.prototype.getTilePixelRatio = function(opt_pixelRatio) {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
ol.source.VectorTile.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
|
ol.source.VectorTile.prototype.getTilePixelSize = function(z, pixelRatio, projection) {
|
||||||
var tileSize = ol.size.toSize(this.tileGrid.getTileSize(z));
|
var tileSize = ol.size.toSize(this.getTileGridForProjection(projection).getTileSize(z));
|
||||||
return [Math.round(tileSize[0] * pixelRatio), Math.round(tileSize[1] * pixelRatio)];
|
return [Math.round(tileSize[0] * pixelRatio), Math.round(tileSize[1] * pixelRatio)];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -59,14 +59,6 @@ ol.Tile.prototype.changed = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the HTML image element for this tile (may be a Canvas, Image, or Video).
|
|
||||||
* @abstract
|
|
||||||
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
|
||||||
*/
|
|
||||||
ol.Tile.prototype.getImage = function() {};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {string} Key.
|
* @return {string} Key.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ ol.tilegrid.createForExtent = function(extent, opt_maxZoom, opt_tileSize, opt_co
|
|||||||
/**
|
/**
|
||||||
* Creates a tile grid with a standard XYZ tiling scheme.
|
* Creates a tile grid with a standard XYZ tiling scheme.
|
||||||
* @param {olx.tilegrid.XYZOptions=} opt_options Tile grid options.
|
* @param {olx.tilegrid.XYZOptions=} opt_options Tile grid options.
|
||||||
* @return {ol.tilegrid.TileGrid} Tile grid instance.
|
* @return {!ol.tilegrid.TileGrid} Tile grid instance.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
ol.tilegrid.createXYZ = function(opt_options) {
|
ol.tilegrid.createXYZ = function(opt_options) {
|
||||||
@@ -126,7 +126,8 @@ ol.tilegrid.resolutionsFromExtent = function(extent, opt_maxZoom, opt_tileSize)
|
|||||||
* @param {ol.ProjectionLike} projection Projection.
|
* @param {ol.ProjectionLike} projection Projection.
|
||||||
* @param {number=} opt_maxZoom Maximum zoom level (default is
|
* @param {number=} opt_maxZoom Maximum zoom level (default is
|
||||||
* ol.DEFAULT_MAX_ZOOM).
|
* ol.DEFAULT_MAX_ZOOM).
|
||||||
* @param {ol.Size=} opt_tileSize Tile size (default uses ol.DEFAULT_TILE_SIZE).
|
* @param {number|ol.Size=} opt_tileSize Tile size (default uses
|
||||||
|
* ol.DEFAULT_TILE_SIZE).
|
||||||
* @param {ol.extent.Corner=} opt_corner Extent corner (default is
|
* @param {ol.extent.Corner=} opt_corner Extent corner (default is
|
||||||
* ol.extent.Corner.BOTTOM_LEFT).
|
* ol.extent.Corner.BOTTOM_LEFT).
|
||||||
* @return {!ol.tilegrid.TileGrid} TileGrid instance.
|
* @return {!ol.tilegrid.TileGrid} TileGrid instance.
|
||||||
|
|||||||
@@ -652,8 +652,7 @@ ol.TilePriorityFunction;
|
|||||||
* dirty: boolean,
|
* dirty: boolean,
|
||||||
* renderedRenderOrder: (null|ol.RenderOrderFunction),
|
* renderedRenderOrder: (null|ol.RenderOrderFunction),
|
||||||
* renderedTileRevision: number,
|
* renderedTileRevision: number,
|
||||||
* renderedRevision: number,
|
* renderedRevision: number}}
|
||||||
* replayGroup: ol.render.ReplayGroup}}
|
|
||||||
*/
|
*/
|
||||||
ol.TileReplayState;
|
ol.TileReplayState;
|
||||||
|
|
||||||
|
|||||||
291
src/ol/vectorimagetile.js
Normal file
291
src/ol/vectorimagetile.js
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
goog.provide('ol.VectorImageTile');
|
||||||
|
|
||||||
|
goog.require('ol');
|
||||||
|
goog.require('ol.Tile');
|
||||||
|
goog.require('ol.TileState');
|
||||||
|
goog.require('ol.array');
|
||||||
|
goog.require('ol.dom');
|
||||||
|
goog.require('ol.events');
|
||||||
|
goog.require('ol.extent');
|
||||||
|
goog.require('ol.events.EventType');
|
||||||
|
goog.require('ol.featureloader');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends {ol.Tile}
|
||||||
|
* @param {ol.TileCoord} tileCoord Tile coordinate.
|
||||||
|
* @param {ol.TileState} state State.
|
||||||
|
* @param {string} src Data source url.
|
||||||
|
* @param {ol.format.Feature} format Feature format.
|
||||||
|
* @param {ol.TileLoadFunctionType} tileLoadFunction Tile load function.
|
||||||
|
* @param {ol.TileCoord} urlTileCoord Wrapped tile coordinate for source urls.
|
||||||
|
* @param {ol.TileUrlFunctionType} tileUrlFunction Tile url function.
|
||||||
|
* @param {ol.tilegrid.TileGrid} sourceTileGrid Tile grid of the source.
|
||||||
|
* @param {ol.tilegrid.TileGrid} tileGrid Tile grid of the renderer.
|
||||||
|
* @param {Object.<string,ol.VectorTile>} sourceTiles Source tiles.
|
||||||
|
* @param {number} pixelRatio Pixel ratio.
|
||||||
|
* @param {ol.proj.Projection} projection Projection.
|
||||||
|
* @param {function(new: ol.VectorTile, ol.TileCoord, ol.TileState, string,
|
||||||
|
* ol.format.Feature, ol.TileLoadFunctionType)} tileClass Class to
|
||||||
|
* instantiate for source tiles.
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile = function(tileCoord, state, src, format, tileLoadFunction,
|
||||||
|
urlTileCoord, tileUrlFunction, sourceTileGrid, tileGrid, sourceTiles,
|
||||||
|
pixelRatio, projection, tileClass) {
|
||||||
|
|
||||||
|
ol.Tile.call(this, tileCoord, state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {CanvasRenderingContext2D}
|
||||||
|
*/
|
||||||
|
this.context_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {ol.format.Feature}
|
||||||
|
*/
|
||||||
|
this.format_ = format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {ol.FeatureLoader}
|
||||||
|
*/
|
||||||
|
this.loader_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {ol.TileReplayState}
|
||||||
|
*/
|
||||||
|
this.replayState_ = {
|
||||||
|
dirty: false,
|
||||||
|
renderedRenderOrder: null,
|
||||||
|
renderedRevision: -1,
|
||||||
|
renderedTileRevision: -1
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {Object.<string,ol.VectorTile>}
|
||||||
|
*/
|
||||||
|
this.sourceTiles_ = sourceTiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keys of source tiles used by this tile. Use with {@link #getTile}.
|
||||||
|
* @type {Array.<string>}
|
||||||
|
*/
|
||||||
|
this.tileKeys = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
this.src_ = src;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {ol.TileCoord}
|
||||||
|
*/
|
||||||
|
this.wrappedTileCoord = urlTileCoord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Array.<ol.EventsKey>}
|
||||||
|
*/
|
||||||
|
this.loadListenerKeys_ = [];
|
||||||
|
|
||||||
|
if (urlTileCoord) {
|
||||||
|
var extent = tileGrid.getTileCoordExtent(urlTileCoord);
|
||||||
|
var resolution = tileGrid.getResolution(tileCoord[0]);
|
||||||
|
var sourceZ = sourceTileGrid.getZForResolution(resolution);
|
||||||
|
sourceTileGrid.forEachTileCoord(extent, sourceZ, function(sourceTileCoord) {
|
||||||
|
var sharedExtent = ol.extent.getIntersection(extent,
|
||||||
|
sourceTileGrid.getTileCoordExtent(sourceTileCoord));
|
||||||
|
if (ol.extent.getWidth(sharedExtent) / resolution >= 0.5 &&
|
||||||
|
ol.extent.getHeight(sharedExtent) / resolution >= 0.5) {
|
||||||
|
// only include source tile if overlap is at least 1 pixel
|
||||||
|
var sourceTileKey = sourceTileCoord.toString();
|
||||||
|
var sourceTile = sourceTiles[sourceTileKey];
|
||||||
|
if (!sourceTile) {
|
||||||
|
var tileUrl = tileUrlFunction(sourceTileCoord, pixelRatio, projection);
|
||||||
|
sourceTile = sourceTiles[sourceTileKey] = new tileClass(sourceTileCoord,
|
||||||
|
tileUrl == undefined ? ol.TileState.EMPTY : ol.TileState.IDLE,
|
||||||
|
tileUrl == undefined ? '' : tileUrl,
|
||||||
|
format, tileLoadFunction);
|
||||||
|
}
|
||||||
|
sourceTile.consumers++;
|
||||||
|
this.tileKeys.push(sourceTileKey);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
ol.inherits(ol.VectorImageTile, ol.Tile);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.disposeInternal = function() {
|
||||||
|
for (var i = 0, ii = this.tileKeys.length; i < ii; ++i) {
|
||||||
|
var sourceTileKey = this.tileKeys[i];
|
||||||
|
var sourceTile = this.getTile(sourceTileKey);
|
||||||
|
sourceTile.consumers--;
|
||||||
|
if (sourceTile.consumers == 0) {
|
||||||
|
delete this.sourceTiles_[sourceTileKey];
|
||||||
|
sourceTile.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.tileKeys.length = 0;
|
||||||
|
this.sourceTiles_ = null;
|
||||||
|
if (this.state == ol.TileState.LOADING) {
|
||||||
|
this.loadListenerKeys_.forEach(ol.events.unlistenByKey);
|
||||||
|
this.loadListenerKeys_.length = 0;
|
||||||
|
}
|
||||||
|
if (this.interimTile) {
|
||||||
|
this.interimTile.dispose();
|
||||||
|
}
|
||||||
|
this.state = ol.TileState.ABORT;
|
||||||
|
this.changed();
|
||||||
|
ol.Tile.prototype.disposeInternal.call(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {CanvasRenderingContext2D} The rendering context.
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.getContext = function() {
|
||||||
|
if (!this.context_) {
|
||||||
|
this.context_ = ol.dom.createCanvasContext2D();
|
||||||
|
}
|
||||||
|
return this.context_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Canvas for this tile.
|
||||||
|
* @return {HTMLCanvasElement} Canvas.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.getImage = function() {
|
||||||
|
return this.replayState_.renderedTileRevision == -1 ?
|
||||||
|
null : this.context_.canvas;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the feature format assigned for reading this tile's features.
|
||||||
|
* @return {ol.format.Feature} Feature format.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.getFormat = function() {
|
||||||
|
return this.format_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {ol.TileReplayState} The replay state.
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.getReplayState = function() {
|
||||||
|
return this.replayState_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.getKey = function() {
|
||||||
|
return this.tileKeys.join('/') + '/' + this.src_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} tileKey Key (tileCoord) of the source tile.
|
||||||
|
* @return {ol.VectorTile} Source tile.
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.getTile = function(tileKey) {
|
||||||
|
return this.sourceTiles_[tileKey];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.load = function() {
|
||||||
|
var leftToLoad = 0;
|
||||||
|
var errors = false;
|
||||||
|
if (this.state == ol.TileState.IDLE) {
|
||||||
|
this.setState(ol.TileState.LOADING);
|
||||||
|
}
|
||||||
|
if (this.state == ol.TileState.LOADING) {
|
||||||
|
this.tileKeys.forEach(function(sourceTileKey) {
|
||||||
|
var sourceTile = this.getTile(sourceTileKey);
|
||||||
|
if (sourceTile.state == ol.TileState.IDLE) {
|
||||||
|
sourceTile.setLoader(this.loader_);
|
||||||
|
sourceTile.load();
|
||||||
|
} else if (sourceTile.state == ol.TileState.ERROR) {
|
||||||
|
errors = true;
|
||||||
|
} else if (sourceTile.state == ol.TileState.EMPTY) {
|
||||||
|
ol.array.remove(this.tileKeys, sourceTileKey);
|
||||||
|
}
|
||||||
|
if (sourceTile.state == ol.TileState.LOADING) {
|
||||||
|
var key = ol.events.listen(sourceTile, ol.events.EventType.CHANGE, function(e) {
|
||||||
|
var state = sourceTile.getState();
|
||||||
|
if (state == ol.TileState.LOADED ||
|
||||||
|
state == ol.TileState.ERROR) {
|
||||||
|
--leftToLoad;
|
||||||
|
ol.events.unlistenByKey(key);
|
||||||
|
ol.array.remove(this.loadListenerKeys_, key);
|
||||||
|
if (state == ol.TileState.ERROR) {
|
||||||
|
ol.array.remove(this.tileKeys, sourceTileKey);
|
||||||
|
errors = true;
|
||||||
|
}
|
||||||
|
if (leftToLoad == 0) {
|
||||||
|
this.setState(this.tileKeys.length > 0 ?
|
||||||
|
ol.TileState.LOADED : ol.TileState.ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
this.loadListenerKeys_.push(key);
|
||||||
|
++leftToLoad;
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
if (leftToLoad == 0) {
|
||||||
|
setTimeout(function() {
|
||||||
|
this.setState(this.tileKeys.length > 0 ?
|
||||||
|
ol.TileState.LOADED :
|
||||||
|
(errors ? ol.TileState.ERROR : ol.TileState.EMPTY));
|
||||||
|
}.bind(this), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array.<ol.Feature>} features Features.
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.setFeatures = function(features) {
|
||||||
|
this.features_ = features;
|
||||||
|
this.setState(ol.TileState.LOADED);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ol.TileState} tileState Tile state.
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.prototype.setState = function(tileState) {
|
||||||
|
this.state = tileState;
|
||||||
|
this.changed();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the loader for a tile.
|
||||||
|
* @param {ol.VectorTile} tile Vector tile.
|
||||||
|
* @param {string} url URL.
|
||||||
|
*/
|
||||||
|
ol.VectorImageTile.defaultLoadFunction = function(tile, url) {
|
||||||
|
var loader = ol.featureloader.loadFeaturesXhr(
|
||||||
|
url, tile.getFormat(), tile.onLoad_.bind(tile), tile.onError_.bind(tile));
|
||||||
|
|
||||||
|
tile.setLoader(loader);
|
||||||
|
};
|
||||||
@@ -3,8 +3,6 @@ goog.provide('ol.VectorTile');
|
|||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.Tile');
|
goog.require('ol.Tile');
|
||||||
goog.require('ol.TileState');
|
goog.require('ol.TileState');
|
||||||
goog.require('ol.dom');
|
|
||||||
goog.require('ol.featureloader');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,10 +19,9 @@ ol.VectorTile = function(tileCoord, state, src, format, tileLoadFunction) {
|
|||||||
ol.Tile.call(this, tileCoord, state);
|
ol.Tile.call(this, tileCoord, state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @type {number}
|
||||||
* @type {CanvasRenderingContext2D}
|
|
||||||
*/
|
*/
|
||||||
this.context_ = null;
|
this.consumers = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -51,17 +48,7 @@ ol.VectorTile = function(tileCoord, state, src, format, tileLoadFunction) {
|
|||||||
*/
|
*/
|
||||||
this.projection_;
|
this.projection_;
|
||||||
|
|
||||||
/**
|
this.replayGroups_ = {};
|
||||||
* @private
|
|
||||||
* @type {ol.TileReplayState}
|
|
||||||
*/
|
|
||||||
this.replayState_ = {
|
|
||||||
dirty: false,
|
|
||||||
renderedRenderOrder: null,
|
|
||||||
renderedRevision: -1,
|
|
||||||
renderedTileRevision: -1,
|
|
||||||
replayGroup: null
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -79,26 +66,6 @@ ol.VectorTile = function(tileCoord, state, src, format, tileLoadFunction) {
|
|||||||
ol.inherits(ol.VectorTile, ol.Tile);
|
ol.inherits(ol.VectorTile, ol.Tile);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {CanvasRenderingContext2D} The rendering context.
|
|
||||||
*/
|
|
||||||
ol.VectorTile.prototype.getContext = function() {
|
|
||||||
if (!this.context_) {
|
|
||||||
this.context_ = ol.dom.createCanvasContext2D();
|
|
||||||
}
|
|
||||||
return this.context_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
ol.VectorTile.prototype.getImage = function() {
|
|
||||||
return this.replayState_.renderedTileRevision == -1 ?
|
|
||||||
null : this.context_.canvas;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the feature format assigned for reading this tile's features.
|
* Get the feature format assigned for reading this tile's features.
|
||||||
* @return {ol.format.Feature} Feature format.
|
* @return {ol.format.Feature} Feature format.
|
||||||
@@ -117,14 +84,6 @@ ol.VectorTile.prototype.getFeatures = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {ol.TileReplayState} The replay state.
|
|
||||||
*/
|
|
||||||
ol.VectorTile.prototype.getReplayState = function() {
|
|
||||||
return this.replayState_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@@ -141,6 +100,11 @@ ol.VectorTile.prototype.getProjection = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ol.VectorTile.prototype.getReplayGroup = function(key) {
|
||||||
|
return this.replayGroups_[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@@ -192,6 +156,11 @@ ol.VectorTile.prototype.setProjection = function(projection) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ol.VectorTile.prototype.setReplayGroup = function(key, replayGroup) {
|
||||||
|
this.replayGroups_[key] = replayGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ol.TileState} tileState Tile state.
|
* @param {ol.TileState} tileState Tile state.
|
||||||
*/
|
*/
|
||||||
@@ -209,16 +178,3 @@ ol.VectorTile.prototype.setState = function(tileState) {
|
|||||||
ol.VectorTile.prototype.setLoader = function(loader) {
|
ol.VectorTile.prototype.setLoader = function(loader) {
|
||||||
this.loader_ = loader;
|
this.loader_ = loader;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the loader for a tile.
|
|
||||||
* @param {ol.VectorTile} tile Vector tile.
|
|
||||||
* @param {string} url URL.
|
|
||||||
*/
|
|
||||||
ol.VectorTile.defaultLoadFunction = function(tile, url) {
|
|
||||||
var loader = ol.featureloader.loadFeaturesXhr(
|
|
||||||
url, tile.getFormat(), tile.onLoad_.bind(tile), tile.onError_.bind(tile));
|
|
||||||
|
|
||||||
tile.setLoader(loader);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -62,6 +62,11 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
|
|||||||
tileClass: TileClass,
|
tileClass: TileClass,
|
||||||
tileGrid: ol.tilegrid.createXYZ()
|
tileGrid: ol.tilegrid.createXYZ()
|
||||||
});
|
});
|
||||||
|
source.getTile = function() {
|
||||||
|
var tile = ol.source.VectorTile.prototype.getTile.apply(source, arguments);
|
||||||
|
tile.setState(ol.TileState.LOADED);
|
||||||
|
return tile;
|
||||||
|
};
|
||||||
layer = new ol.layer.VectorTile({
|
layer = new ol.layer.VectorTile({
|
||||||
source: source,
|
source: source,
|
||||||
style: layerStyle
|
style: layerStyle
|
||||||
@@ -156,12 +161,18 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
|
|||||||
tileGrid: ol.tilegrid.createXYZ()
|
tileGrid: ol.tilegrid.createXYZ()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
var tile = new ol.VectorTile([0, 0, 0], 2);
|
var sourceTile = new ol.VectorTile([0, 0, 0], 2);
|
||||||
tile.projection_ = ol.proj.get('EPSG:3857');
|
sourceTile.setProjection(ol.proj.get('EPSG:3857'));
|
||||||
tile.features_ = [];
|
sourceTile.features_ = [];
|
||||||
tile.getImage = function() {
|
sourceTile.getImage = function() {
|
||||||
return document.createElement('canvas');
|
return document.createElement('canvas');
|
||||||
};
|
};
|
||||||
|
var tile = new ol.VectorImageTile([0, 0, 0]);
|
||||||
|
tile.wrappedTileCoord = [0, 0, 0];
|
||||||
|
tile.setState(ol.TileState.LOADED);
|
||||||
|
tile.getSourceTile = function() {
|
||||||
|
return sourceTile;
|
||||||
|
};
|
||||||
layer.getSource().getTile = function() {
|
layer.getSource().getTile = function() {
|
||||||
return tile;
|
return tile;
|
||||||
};
|
};
|
||||||
@@ -195,12 +206,19 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
|
|||||||
describe('#forEachFeatureAtCoordinate', function() {
|
describe('#forEachFeatureAtCoordinate', function() {
|
||||||
var layer, renderer, replayGroup;
|
var layer, renderer, replayGroup;
|
||||||
var TileClass = function() {
|
var TileClass = function() {
|
||||||
ol.VectorTile.apply(this, arguments);
|
ol.VectorImageTile.apply(this, arguments);
|
||||||
this.setState('loaded');
|
this.setState('loaded');
|
||||||
this.setProjection(ol.proj.get('EPSG:3857'));
|
var sourceTile = new ol.VectorTile([0, 0, 0]);
|
||||||
this.replayState_.replayGroup = replayGroup;
|
sourceTile.setProjection(ol.proj.get('EPSG:3857'));
|
||||||
|
sourceTile.getReplayGroup = function() {
|
||||||
|
return replayGroup;
|
||||||
|
};
|
||||||
|
var key = sourceTile.tileCoord.toString();
|
||||||
|
this.tileKeys = [key];
|
||||||
|
this.sourceTiles_ = {};
|
||||||
|
this.sourceTiles_[key] = sourceTile;
|
||||||
};
|
};
|
||||||
ol.inherits(TileClass, ol.VectorTile);
|
ol.inherits(TileClass, ol.VectorImageTile);
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
replayGroup = {};
|
replayGroup = {};
|
||||||
@@ -226,6 +244,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
|
|||||||
layerStates: {},
|
layerStates: {},
|
||||||
skippedFeatureUids: {},
|
skippedFeatureUids: {},
|
||||||
viewState: {
|
viewState: {
|
||||||
|
projection: ol.proj.get('EPSG:3857'),
|
||||||
resolution: 1,
|
resolution: 1,
|
||||||
rotation: 0
|
rotation: 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
goog.provide('ol.test.source.VectorTile');
|
goog.provide('ol.test.source.VectorTile');
|
||||||
|
|
||||||
goog.require('ol.VectorTile');
|
goog.require('ol.VectorImageTile');
|
||||||
goog.require('ol.format.MVT');
|
goog.require('ol.format.MVT');
|
||||||
goog.require('ol.proj');
|
goog.require('ol.proj');
|
||||||
goog.require('ol.source.VectorTile');
|
goog.require('ol.source.VectorTile');
|
||||||
@@ -12,7 +12,7 @@ describe('ol.source.VectorTile', function() {
|
|||||||
var format = new ol.format.MVT();
|
var format = new ol.format.MVT();
|
||||||
var source = new ol.source.VectorTile({
|
var source = new ol.source.VectorTile({
|
||||||
format: format,
|
format: format,
|
||||||
tileGrid: ol.tilegrid.createXYZ(),
|
tileGrid: ol.tilegrid.createXYZ({tileSize: 512}),
|
||||||
url: '{z}/{x}/{y}.pbf'
|
url: '{z}/{x}/{y}.pbf'
|
||||||
});
|
});
|
||||||
var tile;
|
var tile;
|
||||||
@@ -29,7 +29,7 @@ describe('ol.source.VectorTile', function() {
|
|||||||
describe('#getTile()', function() {
|
describe('#getTile()', function() {
|
||||||
it('creates a tile with the correct tile class', function() {
|
it('creates a tile with the correct tile class', function() {
|
||||||
tile = source.getTile(0, 0, 0, 1, ol.proj.get('EPSG:3857'));
|
tile = source.getTile(0, 0, 0, 1, ol.proj.get('EPSG:3857'));
|
||||||
expect(tile).to.be.a(ol.VectorTile);
|
expect(tile).to.be.a(ol.VectorImageTile);
|
||||||
});
|
});
|
||||||
it('sets the correct tileCoord on the created tile', function() {
|
it('sets the correct tileCoord on the created tile', function() {
|
||||||
expect(tile.getTileCoord()).to.eql([0, 0, 0]);
|
expect(tile.getTileCoord()).to.eql([0, 0, 0]);
|
||||||
@@ -40,4 +40,11 @@ describe('ol.source.VectorTile', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#getTileGridForProjection', function() {
|
||||||
|
it('creates a tile grid with the source tile grid\'s tile size', function() {
|
||||||
|
var tileGrid = source.getTileGridForProjection(ol.proj.get('EPSG:3857'));
|
||||||
|
expect(tileGrid.getTileSize(0)).to.be(512);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
107
test/spec/ol/vectorimagetile.test.js
Normal file
107
test/spec/ol/vectorimagetile.test.js
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
goog.provide('ol.test.VectorImageTile');
|
||||||
|
|
||||||
|
goog.require('ol.events');
|
||||||
|
goog.require('ol.VectorImageTile');
|
||||||
|
goog.require('ol.VectorTile');
|
||||||
|
goog.require('ol.format.GeoJSON');
|
||||||
|
goog.require('ol.proj');
|
||||||
|
|
||||||
|
|
||||||
|
describe('ol.VectorImageTile', function() {
|
||||||
|
|
||||||
|
it('configures loader that sets features on the source tile', function(done) {
|
||||||
|
var format = new ol.format.GeoJSON();
|
||||||
|
var url = 'spec/ol/data/point.json';
|
||||||
|
var tile = new ol.VectorImageTile([0, 0, 0], 0, url, format,
|
||||||
|
ol.VectorImageTile.defaultLoadFunction, [0, 0, 0], function() {
|
||||||
|
return url;
|
||||||
|
}, ol.tilegrid.createXYZ(), ol.tilegrid.createXYZ(), {},
|
||||||
|
1, ol.proj.get('EPSG:3857'), ol.VectorTile);
|
||||||
|
|
||||||
|
tile.load();
|
||||||
|
var sourceTile = tile.getTile(tile.tileKeys[0]);
|
||||||
|
var loader = sourceTile.loader_;
|
||||||
|
expect(typeof loader).to.be('function');
|
||||||
|
|
||||||
|
ol.events.listen(sourceTile, 'change', function(e) {
|
||||||
|
expect(sourceTile.getFeatures().length).to.be.greaterThan(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets ERROR state when source tiles fail to load', function(done) {
|
||||||
|
var format = new ol.format.GeoJSON();
|
||||||
|
var url = 'spec/ol/data/unavailable.json';
|
||||||
|
var tile = new ol.VectorImageTile([0, 0, 0], 0, url, format,
|
||||||
|
ol.VectorImageTile.defaultLoadFunction, [0, 0, 0], function() {
|
||||||
|
return url;
|
||||||
|
}, ol.tilegrid.createXYZ(), ol.tilegrid.createXYZ(), {},
|
||||||
|
1, ol.proj.get('EPSG:3857'), ol.VectorTile);
|
||||||
|
|
||||||
|
tile.load();
|
||||||
|
|
||||||
|
ol.events.listen(tile, 'change', function(e) {
|
||||||
|
expect(tile.getState()).to.be(ol.TileState.ERROR);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets EMPTY state when tile has only empty source tiles', function(done) {
|
||||||
|
var format = new ol.format.GeoJSON();
|
||||||
|
var url = '';
|
||||||
|
var tile = new ol.VectorImageTile([0, 0, 0], 0, url, format,
|
||||||
|
ol.VectorImageTile.defaultLoadFunction, [0, 0, 0], function() {},
|
||||||
|
ol.tilegrid.createXYZ(), ol.tilegrid.createXYZ(), {},
|
||||||
|
1, ol.proj.get('EPSG:3857'), ol.VectorTile);
|
||||||
|
|
||||||
|
tile.load();
|
||||||
|
|
||||||
|
ol.events.listen(tile, 'change', function() {
|
||||||
|
expect(tile.getState()).to.be(ol.TileState.EMPTY);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('#dispose() while loading', function() {
|
||||||
|
var format = new ol.format.GeoJSON();
|
||||||
|
var url = 'spec/ol/data/point.json';
|
||||||
|
var tile = new ol.VectorImageTile([0, 0, 0], 0, url, format,
|
||||||
|
ol.VectorImageTile.defaultLoadFunction, [0, 0, 0], function() {
|
||||||
|
return url;
|
||||||
|
}, ol.tilegrid.createXYZ(), ol.tilegrid.createXYZ({tileSize: 512}), {},
|
||||||
|
1, ol.proj.get('EPSG:3857'), ol.VectorTile);
|
||||||
|
|
||||||
|
tile.load();
|
||||||
|
expect(tile.loadListenerKeys_.length).to.be(4);
|
||||||
|
expect(tile.tileKeys.length).to.be(4);
|
||||||
|
expect(tile.getState()).to.be(ol.TileState.LOADING);
|
||||||
|
tile.dispose();
|
||||||
|
expect(tile.loadListenerKeys_.length).to.be(0);
|
||||||
|
expect(tile.tileKeys.length).to.be(0);
|
||||||
|
expect(tile.sourceTiles_).to.be(null);
|
||||||
|
expect(tile.getState()).to.be(ol.TileState.ABORT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('#dispose() when loaded', function(done) {
|
||||||
|
var format = new ol.format.GeoJSON();
|
||||||
|
var url = 'spec/ol/data/point.json';
|
||||||
|
var tile = new ol.VectorImageTile([0, 0, 0], 0, url, format,
|
||||||
|
ol.VectorImageTile.defaultLoadFunction, [0, 0, 0], function() {
|
||||||
|
return url;
|
||||||
|
}, ol.tilegrid.createXYZ(), ol.tilegrid.createXYZ({tileSize: 512}), {},
|
||||||
|
1, ol.proj.get('EPSG:3857'), ol.VectorTile);
|
||||||
|
|
||||||
|
tile.load();
|
||||||
|
ol.events.listenOnce(tile, 'change', function() {
|
||||||
|
expect(tile.getState()).to.be(ol.TileState.LOADED);
|
||||||
|
expect(tile.loadListenerKeys_.length).to.be(0);
|
||||||
|
expect(tile.tileKeys.length).to.be(4);
|
||||||
|
tile.dispose();
|
||||||
|
expect(tile.tileKeys.length).to.be(0);
|
||||||
|
expect(tile.sourceTiles_).to.be(null);
|
||||||
|
expect(tile.getState()).to.be(ol.TileState.ABORT);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -1,39 +1,14 @@
|
|||||||
goog.provide('ol.test.VectorTile');
|
goog.provide('ol.test.VectorTile');
|
||||||
|
|
||||||
goog.require('ol.events');
|
goog.require('ol.events');
|
||||||
|
goog.require('ol.VectorImageTile');
|
||||||
goog.require('ol.VectorTile');
|
goog.require('ol.VectorTile');
|
||||||
goog.require('ol.Feature');
|
goog.require('ol.Feature');
|
||||||
goog.require('ol.format.GeoJSON');
|
|
||||||
goog.require('ol.format.TextFeature');
|
goog.require('ol.format.TextFeature');
|
||||||
goog.require('ol.proj');
|
goog.require('ol.proj');
|
||||||
|
|
||||||
|
|
||||||
describe('ol.VectorTile.defaultLoadFunction()', function() {
|
describe('ol.VectorTile', function() {
|
||||||
|
|
||||||
it('sets the loader function on the tile', function() {
|
|
||||||
var format = new ol.format.GeoJSON();
|
|
||||||
var tile = new ol.VectorTile([0, 0, 0], null, null, format);
|
|
||||||
var url = 'https://example.com/';
|
|
||||||
|
|
||||||
ol.VectorTile.defaultLoadFunction(tile, url);
|
|
||||||
var loader = tile.loader_;
|
|
||||||
expect(typeof loader).to.be('function');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loader sets features on the tile', function(done) {
|
|
||||||
var format = new ol.format.GeoJSON();
|
|
||||||
var tile = new ol.VectorTile([0, 0, 0], null, null, format);
|
|
||||||
var url = 'spec/ol/data/point.json';
|
|
||||||
|
|
||||||
ol.VectorTile.defaultLoadFunction(tile, url);
|
|
||||||
var loader = tile.loader_;
|
|
||||||
|
|
||||||
ol.events.listen(tile, 'change', function(e) {
|
|
||||||
expect(tile.getFeatures().length).to.be.greaterThan(0);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
loader.call(tile, [], 1, ol.proj.get('EPSG:3857'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loader sets features on the tile and updates proj units', function(done) {
|
it('loader sets features on the tile and updates proj units', function(done) {
|
||||||
// mock format that return a tile-pixels feature
|
// mock format that return a tile-pixels feature
|
||||||
@@ -51,7 +26,7 @@ describe('ol.VectorTile.defaultLoadFunction()', function() {
|
|||||||
var tile = new ol.VectorTile([0, 0, 0], null, null, format);
|
var tile = new ol.VectorTile([0, 0, 0], null, null, format);
|
||||||
var url = 'spec/ol/data/point.json';
|
var url = 'spec/ol/data/point.json';
|
||||||
|
|
||||||
ol.VectorTile.defaultLoadFunction(tile, url);
|
ol.VectorImageTile.defaultLoadFunction(tile, url);
|
||||||
var loader = tile.loader_;
|
var loader = tile.loader_;
|
||||||
ol.events.listen(tile, 'change', function(e) {
|
ol.events.listen(tile, 'change', function(e) {
|
||||||
expect(tile.getFeatures().length).to.be.greaterThan(0);
|
expect(tile.getFeatures().length).to.be.greaterThan(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user