Clip tile layers by extent

This commit is contained in:
Tim Schaub
2018-11-16 12:34:09 +01:00
parent 73ffda10db
commit 038f122d11
6 changed files with 82 additions and 50 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -1,47 +0,0 @@
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {fromLonLat} from '../../../src/ol/proj';
import XYZ from '../../../src/ol/source/XYZ';
import {getSize} from '../../../src/ol/extent';
const center = fromLonLat([8.6, 50.1]);
const map = new Map({
target: 'map',
view: new View({
center: center,
zoom: 3
})
});
const layerExtent = centerExtent();
map.addLayer(
new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg'
}),
extent: layerExtent
}),
);
map.addLayer(
new TileLayer({
source: new XYZ({
url: '/data/tiles/stamen-labels/{z}/{x}/{y}.png'
}),
extent: layerExtent
})
);
render();
function centerExtent() {
const c = map.getView().calculateExtent([256, 256]);
const qw = getSize(c)[0] / 4;
const qh = getSize(c)[1] / 4;
return [c[0] + qw, c[1] + qh, c[2] - qw, c[3] - qh];
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

@@ -0,0 +1,40 @@
/**
* Tile layers get clipped to their extent.
*/
import Map from '../../../src/ol/Map.js';
import View from '../../../src/ol/View.js';
import TileLayer from '../../../src/ol/layer/Tile.js';
import {fromLonLat} from '../../../src/ol/proj';
import {transformExtent} from '../../../src/ol/proj.js';
import XYZ from '../../../src/ol/source/XYZ';
const center = fromLonLat([7, 50]);
const extent = transformExtent([2, 47, 10, 53], 'EPSG:4326', 'EPSG:3857');
new Map({
target: 'map',
view: new View({
center: center,
zoom: 3
}),
layers: [
new TileLayer({
source: new XYZ({
url: '/data/tiles/satellite/{z}/{x}/{y}.jpg',
maxZoom: 3
}),
extent: extent
}),
new TileLayer({
source: new XYZ({
url: '/data/tiles/stamen-labels/{z}/{x}/{y}.png',
minZoom: 3,
maxZoom: 5
}),
extent: extent
})
]
});
render();

View File

@@ -85,6 +85,39 @@ class CanvasLayerRenderer extends LayerRenderer {
rotateAtOffset(context, rotation, halfWidth, halfHeight);
}
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
* @param {import("../../extent.js").Extent} extent Clip extent.
* @protected
*/
clipUnrotated(context, frameState, extent) {
const topLeft = getTopLeft(extent);
const topRight = getTopRight(extent);
const bottomRight = getBottomRight(extent);
const bottomLeft = getBottomLeft(extent);
applyTransform(frameState.coordinateToPixelTransform, topLeft);
applyTransform(frameState.coordinateToPixelTransform, topRight);
applyTransform(frameState.coordinateToPixelTransform, bottomRight);
applyTransform(frameState.coordinateToPixelTransform, bottomLeft);
const inverted = invertTransform(this.pixelTransform_.slice());
applyTransform(inverted, topLeft);
applyTransform(inverted, topRight);
applyTransform(inverted, bottomRight);
applyTransform(inverted, bottomLeft);
context.save();
context.beginPath();
context.moveTo(Math.round(topLeft[0]), Math.round(topLeft[1]));
context.lineTo(Math.round(topRight[0]), Math.round(topRight[1]));
context.lineTo(Math.round(bottomRight[0]), Math.round(bottomRight[1]));
context.lineTo(Math.round(bottomLeft[0]), Math.round(bottomLeft[1]));
context.clip();
}
/**
* @param {import("../../render/EventType.js").default} type Event type.
* @param {CanvasRenderingContext2D} context Context.

View File

@@ -143,12 +143,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
const tileResolution = tileGrid.getResolution(z);
let extent = frameState.extent;
if (layerState.extent !== undefined) {
if (layerState.extent) {
extent = getIntersection(extent, layerState.extent);
}
// TODO: clip by layer extent
const tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio);
// desired dimensions of the canvas in pixels
@@ -235,6 +233,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
context.clearRect(0, 0, width, height);
}
if (layerState.extent) {
this.clipUnrotated(context, frameState, layerState.extent);
}
this.preRender(context, frameState, pixelTransform);
this.renderedTiles.length = 0;
@@ -285,6 +287,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
this.postRender(context, frameState, pixelTransform);
if (layerState.extent) {
context.restore();
}
const opacity = layerState.opacity;
if (opacity !== canvas.style.opacity) {
canvas.style.opacity = opacity;