Merge pull request #4557 from ahocevar/vectortile-canvas
Conditionally render tiles to a separate tile canvas
This commit is contained in:
@@ -139,6 +139,12 @@ ol.render.canvas.Replay = function(tolerance, maxExtent, resolution) {
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.tmpLocalTransform_ = goog.vec.Mat4.createNumber();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {!goog.vec.Mat4.Number}
|
||||
*/
|
||||
this.tmpLocalTransformInv_ = goog.vec.Mat4.createNumber();
|
||||
};
|
||||
goog.inherits(ol.render.canvas.Replay, ol.render.VectorContext);
|
||||
|
||||
@@ -252,6 +258,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
||||
var d = 0; // data index
|
||||
var dd; // end of per-instruction data
|
||||
var localTransform = this.tmpLocalTransform_;
|
||||
var localTransformInv = this.tmpLocalTransformInv_;
|
||||
var prevX, prevY, roundX, roundY;
|
||||
while (i < ii) {
|
||||
var instruction = instructions[i];
|
||||
@@ -331,7 +338,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
||||
ol.vec.Mat4.makeTransform2D(
|
||||
localTransform, centerX, centerY, scale, scale,
|
||||
rotation, -centerX, -centerY);
|
||||
context.setTransform(
|
||||
context.transform(
|
||||
goog.vec.Mat4.getElement(localTransform, 0, 0),
|
||||
goog.vec.Mat4.getElement(localTransform, 1, 0),
|
||||
goog.vec.Mat4.getElement(localTransform, 0, 1),
|
||||
@@ -351,7 +358,14 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
||||
context.globalAlpha = alpha;
|
||||
}
|
||||
if (scale != 1 || rotation !== 0) {
|
||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
goog.vec.Mat4.invert(localTransform, localTransformInv);
|
||||
context.transform(
|
||||
goog.vec.Mat4.getElement(localTransformInv, 0, 0),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 1, 0),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 0, 1),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 1, 1),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 0, 3),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 1, 3));
|
||||
}
|
||||
}
|
||||
++i;
|
||||
@@ -390,7 +404,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
||||
if (scale != 1 || rotation !== 0) {
|
||||
ol.vec.Mat4.makeTransform2D(
|
||||
localTransform, x, y, scale, scale, rotation, -x, -y);
|
||||
context.setTransform(
|
||||
context.transform(
|
||||
goog.vec.Mat4.getElement(localTransform, 0, 0),
|
||||
goog.vec.Mat4.getElement(localTransform, 1, 0),
|
||||
goog.vec.Mat4.getElement(localTransform, 0, 1),
|
||||
@@ -427,7 +441,14 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
||||
}
|
||||
|
||||
if (scale != 1 || rotation !== 0) {
|
||||
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||
goog.vec.Mat4.invert(localTransform, localTransformInv);
|
||||
context.transform(
|
||||
goog.vec.Mat4.getElement(localTransformInv, 0, 0),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 1, 0),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 0, 1),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 1, 1),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 0, 3),
|
||||
goog.vec.Mat4.getElement(localTransformInv, 1, 3));
|
||||
}
|
||||
}
|
||||
++i;
|
||||
@@ -1995,32 +2016,35 @@ ol.render.canvas.ReplayGroup.prototype.isEmpty = function() {
|
||||
* @param {number} viewRotation View rotation.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {boolean=} opt_clip Clip at `maxExtent`. Default is true.
|
||||
*/
|
||||
ol.render.canvas.ReplayGroup.prototype.replay = function(
|
||||
context, pixelRatio, transform, viewRotation, skippedFeaturesHash) {
|
||||
ol.render.canvas.ReplayGroup.prototype.replay = function(context, pixelRatio,
|
||||
transform, viewRotation, skippedFeaturesHash, opt_clip) {
|
||||
|
||||
/** @type {Array.<number>} */
|
||||
var zs = Object.keys(this.replaysByZIndex_).map(Number);
|
||||
zs.sort(ol.array.numberSafeCompareFunction);
|
||||
|
||||
// setup clipping so that the parts of over-simplified geometries are not
|
||||
// visible outside the current extent when panning
|
||||
var maxExtent = this.maxExtent_;
|
||||
var minX = maxExtent[0];
|
||||
var minY = maxExtent[1];
|
||||
var maxX = maxExtent[2];
|
||||
var maxY = maxExtent[3];
|
||||
var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
|
||||
ol.geom.flat.transform.transform2D(
|
||||
flatClipCoords, 0, 8, 2, transform, flatClipCoords);
|
||||
context.save();
|
||||
context.beginPath();
|
||||
context.moveTo(flatClipCoords[0], flatClipCoords[1]);
|
||||
context.lineTo(flatClipCoords[2], flatClipCoords[3]);
|
||||
context.lineTo(flatClipCoords[4], flatClipCoords[5]);
|
||||
context.lineTo(flatClipCoords[6], flatClipCoords[7]);
|
||||
context.closePath();
|
||||
context.clip();
|
||||
if (opt_clip !== false) {
|
||||
// setup clipping so that the parts of over-simplified geometries are not
|
||||
// visible outside the current extent when panning
|
||||
var maxExtent = this.maxExtent_;
|
||||
var minX = maxExtent[0];
|
||||
var minY = maxExtent[1];
|
||||
var maxX = maxExtent[2];
|
||||
var maxY = maxExtent[3];
|
||||
var flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
|
||||
ol.geom.flat.transform.transform2D(
|
||||
flatClipCoords, 0, 8, 2, transform, flatClipCoords);
|
||||
context.save();
|
||||
context.beginPath();
|
||||
context.moveTo(flatClipCoords[0], flatClipCoords[1]);
|
||||
context.lineTo(flatClipCoords[2], flatClipCoords[3]);
|
||||
context.lineTo(flatClipCoords[4], flatClipCoords[5]);
|
||||
context.lineTo(flatClipCoords[6], flatClipCoords[7]);
|
||||
context.closePath();
|
||||
context.clip();
|
||||
}
|
||||
|
||||
var i, ii, j, jj, replays, replay;
|
||||
for (i = 0, ii = zs.length; i < ii; ++i) {
|
||||
|
||||
@@ -11,6 +11,7 @@ goog.require('ol.ViewHint');
|
||||
goog.require('ol.array');
|
||||
goog.require('ol.dom');
|
||||
goog.require('ol.extent');
|
||||
goog.require('ol.geom.flat.transform');
|
||||
goog.require('ol.layer.VectorTile');
|
||||
goog.require('ol.proj.Units');
|
||||
goog.require('ol.render.EventType');
|
||||
@@ -87,10 +88,14 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
|
||||
var projection = viewState.projection;
|
||||
var resolution = viewState.resolution;
|
||||
var rotation = viewState.rotation;
|
||||
var size = frameState.size;
|
||||
var pixelScale = pixelRatio / resolution;
|
||||
var layer = this.getLayer();
|
||||
var source = layer.getSource();
|
||||
goog.asserts.assertInstanceof(source, ol.source.VectorTile,
|
||||
'Source is an ol.source.VectorTile');
|
||||
var tilePixelRatio = source.getTilePixelRatio();
|
||||
var maxScale = tilePixelRatio / pixelRatio;
|
||||
|
||||
var transform = this.getTransform(frameState, 0);
|
||||
|
||||
@@ -114,35 +119,81 @@ ol.renderer.canvas.VectorTileLayer.prototype.composeFrame =
|
||||
var tilesToDraw = this.renderedTiles_;
|
||||
var tileGrid = source.getTileGrid();
|
||||
|
||||
var currentZ, i, ii, origin, tile, tileSize;
|
||||
var tilePixelRatio, tilePixelResolution, tilePixelSize, tileResolution;
|
||||
var currentZ, height, i, ii, insertPoint, insertTransform, offsetX, offsetY;
|
||||
var origin, pixelSpace, replayState, scale, tile, tileCenter, tileContext;
|
||||
var tileExtent, tilePixelResolution, tilePixelSize, tileResolution, tileSize;
|
||||
var tileTransform, width;
|
||||
for (i = 0, ii = tilesToDraw.length; i < ii; ++i) {
|
||||
tile = tilesToDraw[i];
|
||||
replayState = tile.getReplayState();
|
||||
tileExtent = tileGrid.getTileCoordExtent(
|
||||
tile.getTileCoord(), this.tmpExtent_);
|
||||
currentZ = tile.getTileCoord()[0];
|
||||
tileSize = tileGrid.getTileSize(currentZ);
|
||||
tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection);
|
||||
tilePixelRatio = tilePixelSize[0] /
|
||||
ol.size.toSize(tileSize, this.tmpSize_)[0];
|
||||
tileSize = ol.size.toSize(tileGrid.getTileSize(currentZ), this.tmpSize_);
|
||||
pixelSpace = tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS;
|
||||
tileResolution = tileGrid.getResolution(currentZ);
|
||||
tilePixelResolution = tileResolution / tilePixelRatio;
|
||||
if (tile.getProjection().getUnits() == ol.proj.Units.TILE_PIXELS) {
|
||||
origin = ol.extent.getTopLeft(tileGrid.getTileCoordExtent(
|
||||
tile.getTileCoord(), this.tmpExtent_));
|
||||
transform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
|
||||
pixelRatio * frameState.size[0] / 2,
|
||||
pixelRatio * frameState.size[1] / 2,
|
||||
pixelRatio * tilePixelResolution / resolution,
|
||||
pixelRatio * tilePixelResolution / resolution,
|
||||
viewState.rotation,
|
||||
(origin[0] - center[0]) / tilePixelResolution,
|
||||
(center[1] - origin[1]) / tilePixelResolution);
|
||||
scale = tileResolution / resolution;
|
||||
offsetX = Math.round(pixelRatio * size[0] / 2);
|
||||
offsetY = Math.round(pixelRatio * size[1] / 2);
|
||||
width = tileSize[0] * pixelRatio * scale;
|
||||
height = tileSize[1] * pixelRatio * scale;
|
||||
if (width < 1 || scale > maxScale) {
|
||||
if (pixelSpace) {
|
||||
origin = ol.extent.getTopLeft(tileExtent);
|
||||
tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
|
||||
offsetX, offsetY,
|
||||
pixelScale * tilePixelResolution,
|
||||
pixelScale * tilePixelResolution,
|
||||
rotation,
|
||||
(origin[0] - center[0]) / tilePixelResolution,
|
||||
(center[1] - origin[1]) / tilePixelResolution);
|
||||
} else {
|
||||
tileTransform = transform;
|
||||
}
|
||||
replayState.replayGroup.replay(replayContext, pixelRatio,
|
||||
tileTransform, rotation, skippedFeatureUids);
|
||||
} else {
|
||||
tilePixelSize = source.getTilePixelSize(currentZ, pixelRatio, projection);
|
||||
if (pixelSpace) {
|
||||
tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
|
||||
0, 0,
|
||||
pixelScale * tilePixelResolution, pixelScale * tilePixelResolution,
|
||||
rotation,
|
||||
-tilePixelSize[0] / 2, -tilePixelSize[1] / 2);
|
||||
} else {
|
||||
tileCenter = ol.extent.getCenter(tileExtent);
|
||||
tileTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
|
||||
0, 0,
|
||||
pixelScale, -pixelScale,
|
||||
-rotation,
|
||||
-tileCenter[0], -tileCenter[1]);
|
||||
}
|
||||
tileContext = tile.getContext();
|
||||
if (replayState.resolution !== resolution ||
|
||||
replayState.rotation !== rotation) {
|
||||
replayState.resolution = resolution;
|
||||
replayState.rotation = rotation;
|
||||
tileContext.canvas.width = width + 0.5;
|
||||
tileContext.canvas.height = height + 0.5;
|
||||
tileContext.translate(width / 2, height / 2);
|
||||
tileContext.rotate(-rotation);
|
||||
replayState.replayGroup.replay(tileContext, pixelRatio,
|
||||
tileTransform, rotation, skippedFeatureUids, false);
|
||||
}
|
||||
insertTransform = ol.vec.Mat4.makeTransform2D(this.tmpTransform_,
|
||||
0, 0, pixelScale, -pixelScale, 0, -center[0], -center[1]);
|
||||
insertPoint = ol.geom.flat.transform.transform2D(
|
||||
ol.extent.getTopLeft(tileExtent), 0, 1, 2, insertTransform);
|
||||
replayContext.translate(offsetX, offsetY);
|
||||
replayContext.rotate(rotation);
|
||||
replayContext.drawImage(tileContext.canvas,
|
||||
Math.round(insertPoint[0]), Math.round(insertPoint[1]));
|
||||
replayContext.rotate(-rotation);
|
||||
replayContext.translate(-offsetX, -offsetY);
|
||||
}
|
||||
tile.getReplayState().replayGroup.replay(replayContext, pixelRatio,
|
||||
transform, rotation, skippedFeatureUids);
|
||||
}
|
||||
|
||||
transform = this.getTransform(frameState, 0);
|
||||
|
||||
if (replayContext != context) {
|
||||
this.dispatchRenderEvent(replayContext, frameState, transform);
|
||||
context.drawImage(replayContext.canvas, 0, 0);
|
||||
@@ -234,6 +285,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.createReplayGroup = function(tile,
|
||||
replayState.renderedRevision = revision;
|
||||
replayState.renderedRenderOrder = renderOrder;
|
||||
replayState.replayGroup = replayGroup;
|
||||
replayState.resolution = NaN;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ goog.require('ol.Tile');
|
||||
goog.require('ol.TileCoord');
|
||||
goog.require('ol.TileLoadFunctionType');
|
||||
goog.require('ol.TileState');
|
||||
goog.require('ol.dom');
|
||||
goog.require('ol.proj.Projection');
|
||||
|
||||
|
||||
@@ -33,6 +34,12 @@ ol.VectorTile =
|
||||
|
||||
goog.base(this, tileCoord, state);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {CanvasRenderingContext2D}
|
||||
*/
|
||||
this.context_ = ol.dom.createCanvasContext2D();
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ol.format.Feature}
|
||||
@@ -84,6 +91,14 @@ ol.VectorTile =
|
||||
goog.inherits(ol.VectorTile, ol.Tile);
|
||||
|
||||
|
||||
/**
|
||||
* @return {CanvasRenderingContext2D}
|
||||
*/
|
||||
ol.VectorTile.prototype.getContext = function() {
|
||||
return this.context_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user