Openlayers contains the powerful feature which enables you to combine 2 (or more) raster layers using a custom function with access to the pixels of each layer.
As vector layers can also be rendered as raster using the renderMode:image
, this can be used to implement client side cropping and/or masking based on any shape.
In the following example I show how the standard OpenStreetMap layer can be combined with a vector circle shape in a variety of ways depending on the operation function:
Combining the OSM raster source with a vector source:
// create the ol.layer.Vector which we will use as the mask
const olLayerVector = new ol.layer.Vector({
// vector layer must be rendered as an image to allow raster composition
renderMode: 'image',
source: new ol.source.Vector({
// here we are just using a simple circle centered on the UK, but there are many possibilities
// GeoJSON, GPX, ol.geom.*
features: [
new ol.Feature({
geometry: new ol.geom.Circle(
ol.proj.fromLonLat([-3.4, 55.3]),
1000000
)
})
]
})
});
// define the composition function, pixels is an array of pixel data arrays
// e.g. pixel[0] is the first layer, pixel[1] the second etc.
// pixels are in the format [r, g, b, α] and the range 0-255
// here we just return the pixel from the first layer, effectively ignoring the vector layer
const olSourceRasterOperation = pixels => {
return pixels[0];
};
// create the raster ol.layer.Image which combines the 2 raster sources using the composition operation function
const olLayerImage = new ol.layer.Image({
source: new ol.source.Raster({
sources: [
new ol.source.OSM(),
olLayerVector
],
operation: olSourceRasterOperationCropInner
})
});
// create the ol.Map
new ol.Map({
target: 'map',
layers: [
olLayerImage
],
view: new ol.View({
center: ol.proj.fromLonLat([-3.4, 55.3]),
zoom: 4
})
});
Crop Inner
const olSourceRasterOperation = pixels => {
if (pixels[1][3] === 0) {
return pixels[0];
} else {
return [0, 0, 0, 0];
}
};
Crop Outer
const olSourceRasterOperation = pixels => {
if (pixels[1][3] === 0) {
return [0, 0, 0, 0];
} else {
return pixels[0];
}
};
Mask Inner With Solid Blue Colour
const olSourceRasterOperation = pixels => {
if (pixels[1][3] === 0) {
return pixels[0];
} else {
return [0, 0, 255, 255];
}
};
Mask Outer With OSM Red Channel
const olSourceRasterOperation = pixels => {
if (pixels[1][3] === 0) {
return [pixels[0][0], 0, 0, 255];
} else {
return pixels[0];
}
};