This is the documentation of version 0.62.2. Go to the latest version, 1.0.0-rc.5.

Depth of field

The map effects plugin's depthOfField holds one distance sharp on a pitched map and defocuses the rest, the way a lens focused there would. It is the one effect that reads the map's camera. In the playground below, the band holds one run of the valley in focus and lets the ridges behind it soften:

Turning it on

effects.set({
    'depthOfField.intensity': 18,  // the widest circle of confusion, in CSS pixels
    'depthOfField.focus': 0,       // 0 = the nearest ground, 1 = the farthest the frame shows
    'depthOfField.band': 0.3,      // how much of that depth stays sharp
    'depthOfField.bokeh': 0.5,     // whether a defocused highlight fades or returns as a disc
});
Knob Range Default
depthOfField.intensity (CSS px) 0–30 0 (off)
depthOfField.focus (0 = nearest, 1 = farthest shown), depthOfField.band 0–1 0, 0.3
depthOfField.bokeh 0–1 0.5

focus: 0 is the automatic answer rather than a neutral middle — the nearest thing in a tilted shot is the bottom edge, so switching the effect on over a tilted city needs nothing set. Raise it and the middle distance is sharp with the foreground and the horizon thrown off, which is the tilt-shift picture.

How it works

It is the one effect that runs on the GPU: a full-screen pass that gathers a disc of the map's own pixels per fragment, at a radius that grows with distance. That is what a backdrop-filter cannot do — one radius for the whole layer, blended over the sharp original, reads as haze rather than as a lens. Because the pass reads the rendered map back as a texture, it needs canvasContextAttributes: { preserveDrawingBuffer: true } on the map, the same attribute bloom and capture() already require.

Bokeh is what separates a defocus from a blur. A lens does not average the light it cannot resolve, it spreads it, so each point arrives as an image of the aperture at its own brightness. Weighting every sample by the fourth power of its brightness keeps a lit road or a traffic tube bright across the whole circle it is spread over; at 0 the light is averaged away, as a blur does. It is deliberately not energy-conserving — normalising that away leaves you with the blur again.

No depth buffer is involved, and none is needed. MapLibre hands none out, but the map is a plane: a ray through row y meets it at 1/z = 1/D − y·tanθ/D², so reciprocal distance — which is what a lens actually defocuses by — is affine in the row of the picture. The whole depth of a frame is then one number, span = 2·tan(fov/2)·tan(pitch) with ramp = span/(1 + span/2): 0 seen from straight above, 0.5 at a 45° tilt, past 1 once the horizon is on screen.

Planning around it

It pairs with 3D terrain, which gives the view relief to defocus — see the 3D terrain playground above, and the route fly-over playground, where it holds the road ahead in focus through the whole flight.

Related guides and examples

Related guides

Related examples