Combining OpenLayers raster and vector layers for cropping and masking

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];
					}
				};
			
		
Load Comments...