Clip tile layers by extent
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 38 KiB |
@@ -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 |
@@ -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();
|
||||||
@@ -85,6 +85,39 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
rotateAtOffset(context, rotation, halfWidth, halfHeight);
|
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 {import("../../render/EventType.js").default} type Event type.
|
||||||
* @param {CanvasRenderingContext2D} context Context.
|
* @param {CanvasRenderingContext2D} context Context.
|
||||||
|
|||||||
@@ -143,12 +143,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
const tileResolution = tileGrid.getResolution(z);
|
const tileResolution = tileGrid.getResolution(z);
|
||||||
let extent = frameState.extent;
|
let extent = frameState.extent;
|
||||||
|
|
||||||
if (layerState.extent !== undefined) {
|
if (layerState.extent) {
|
||||||
extent = getIntersection(extent, layerState.extent);
|
extent = getIntersection(extent, layerState.extent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: clip by layer extent
|
|
||||||
|
|
||||||
const tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio);
|
const tilePixelRatio = tileSource.getTilePixelRatio(pixelRatio);
|
||||||
|
|
||||||
// desired dimensions of the canvas in pixels
|
// desired dimensions of the canvas in pixels
|
||||||
@@ -235,6 +233,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
context.clearRect(0, 0, width, height);
|
context.clearRect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (layerState.extent) {
|
||||||
|
this.clipUnrotated(context, frameState, layerState.extent);
|
||||||
|
}
|
||||||
|
|
||||||
this.preRender(context, frameState, pixelTransform);
|
this.preRender(context, frameState, pixelTransform);
|
||||||
|
|
||||||
this.renderedTiles.length = 0;
|
this.renderedTiles.length = 0;
|
||||||
@@ -285,6 +287,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
|
|
||||||
this.postRender(context, frameState, pixelTransform);
|
this.postRender(context, frameState, pixelTransform);
|
||||||
|
|
||||||
|
if (layerState.extent) {
|
||||||
|
context.restore();
|
||||||
|
}
|
||||||
|
|
||||||
const opacity = layerState.opacity;
|
const opacity = layerState.opacity;
|
||||||
if (opacity !== canvas.style.opacity) {
|
if (opacity !== canvas.style.opacity) {
|
||||||
canvas.style.opacity = opacity;
|
canvas.style.opacity = opacity;
|
||||||
|
|||||||
Reference in New Issue
Block a user