Fill extrusion rounded corners
Use fill-extrusion-rounded-corner-distance to round the corners of extruded polygons.
import * as maplibregl from 'https://unpkg.com/maplibre-gl@6.2.0/dist/maplibre-gl.mjs';
const map = new maplibregl.Map({
style: 'https://tiles.openfreemap.org/styles/bright',
center: [-74.0066, 40.7135],
zoom: 15.5,
pitch: 45,
bearing: -17.6,
container: 'map',
canvasContextAttributes: {antialias: true}
});
map.on('load', () => {
const layers = map.getStyle().layers;
const labelLayerId = layers.find(l => l.type === 'symbol' && l.layout?.['text-field']).id;
const buildingSource = layers.find(l => l['source-layer'] === 'building').source;
map.addLayer({
id: 'building-extrusion',
type: 'fill-extrusion',
source: buildingSource,
'source-layer': 'building',
filter: ['==', ['get', 'render_min_height'], 0],
layout: {
'fill-extrusion-rounded-corner-distance': 2
},
paint: {
'fill-extrusion-color': [
'interpolate', ['linear'], ['get', 'render_height'],
0, 'lightgray', 200, 'royalblue', 400, 'lightblue'
],
'fill-extrusion-height': ['get', 'render_height'],
'fill-extrusion-opacity': 0.8
}
}, labelLayerId);
document.getElementById('corner-radius').addEventListener('input', (e) => {
const val = parseFloat(e.target.value);
e.target.closest('tr').querySelector('span').textContent = val;
map.setLayoutProperty('building-extrusion', 'fill-extrusion-rounded-corner-distance', val);
});
document.getElementById('extrusion-height').addEventListener('input', (e) => {
const val = parseFloat(e.target.value);
e.target.closest('tr').querySelector('span').textContent = val;
map.setPaintProperty('building-extrusion', 'fill-extrusion-height', ['*', val, ['get', 'render_height']]);
});
document.getElementById('extrusion-opacity').addEventListener('input', (e) => {
const val = parseFloat(e.target.value);
e.target.closest('tr').querySelector('span').textContent = val;
map.setPaintProperty('building-extrusion', 'fill-extrusion-opacity', Math.round(val * 100));
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<title>Fill extrusion rounded corners</title>
<meta property="og:description" content="Use fill-extrusion-rounded-corner-distance to round the corners of extruded polygons." />
<meta property="og:category" content="3D Models & Buildings" />
<meta property="og:created" content="2026-07-25" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@6.2.0/dist/maplibre-gl.css' />
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
#controls {
font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;
position: absolute;
top: 10px;
left: 10px;
color: #fff;
background-color: rgba(50, 50, 50, 0.85);
padding: 12px 16px;
border-radius: 6px;
min-width: 280px;
}
#controls table { border-collapse: collapse; width: 100%; }
#controls td { padding: 4px 6px; vertical-align: middle; }
#controls td:last-child { text-align: right; width: 3em; }
#controls label { white-space: nowrap; }
#controls input[type=range] { width: 120px; }
</style>
</head>
<body>
<div id="map"></div>
<div id="controls">
<table>
<tr>
<td><label for="corner-radius">Corner radius (m)</label></td>
<td><input type="range" id="corner-radius" min="0" max="5" step="0.1" value="2" /></td>
<td><span>2</span></td>
</tr>
<tr>
<td><label for="extrusion-height">Height multiplier</label></td>
<td><input type="range" id="extrusion-height" min="0" max="3" step="0.1" value="1" /></td>
<td><span>1</span>×</td>
</tr>
<tr>
<td><label for="extrusion-opacity">Opacity</label></td>
<td><input type="range" id="extrusion-opacity" min="0" max="1" step="0.05" value="0.8" /></td>
<td><span>80</span>%</td>
</tr>
</table>
</div>
<script type="module">
import * as maplibregl from 'https://unpkg.com/maplibre-gl@6.2.0/dist/maplibre-gl.mjs';
const map = new maplibregl.Map({
style: 'https://tiles.openfreemap.org/styles/bright',
center: [-74.0066, 40.7135],
zoom: 15.5,
pitch: 45,
bearing: -17.6,
container: 'map',
canvasContextAttributes: {antialias: true}
});
map.on('load', () => {
const layers = map.getStyle().layers;
const labelLayerId = layers.find(l => l.type === 'symbol' && l.layout?.['text-field']).id;
const buildingSource = layers.find(l => l['source-layer'] === 'building').source;
map.addLayer({
id: 'building-extrusion',
type: 'fill-extrusion',
source: buildingSource,
'source-layer': 'building',
filter: ['==', ['get', 'render_min_height'], 0],
layout: {
'fill-extrusion-rounded-corner-distance': 2
},
paint: {
'fill-extrusion-color': [
'interpolate', ['linear'], ['get', 'render_height'],
0, 'lightgray', 200, 'royalblue', 400, 'lightblue'
],
'fill-extrusion-height': ['get', 'render_height'],
'fill-extrusion-opacity': 0.8
}
}, labelLayerId);
document.getElementById('corner-radius').addEventListener('input', (e) => {
const val = parseFloat(e.target.value);
e.target.closest('tr').querySelector('span').textContent = val;
map.setLayoutProperty('building-extrusion', 'fill-extrusion-rounded-corner-distance', val);
});
document.getElementById('extrusion-height').addEventListener('input', (e) => {
const val = parseFloat(e.target.value);
e.target.closest('tr').querySelector('span').textContent = val;
map.setPaintProperty('building-extrusion', 'fill-extrusion-height', ['*', val, ['get', 'render_height']]);
});
document.getElementById('extrusion-opacity').addEventListener('input', (e) => {
const val = parseFloat(e.target.value);
e.target.closest('tr').querySelector('span').textContent = val;
map.setPaintProperty('building-extrusion', 'fill-extrusion-opacity', Math.round(val * 100));
});
});
</script>
</body>
</html>