Ever wished you could make your Mapbox map look more like a telephoto lens or a dramatic wide-angle shot? Turns out, there's an undocumented way to control the camera's field of view (FOV) in Mapbox GL JS—but with a big caveat: this is not a public API.
⚠️ Developer Warning: What I'm about to show you involves accessing private internal properties. Use this only for experiments, prototypes, and creative projects. Don't rely on this in production—it could break in any future Mapbox version without notice.
The Problem: Fixed Field of View
By default, Mapbox GL JS uses a fixed vertical field of view of approximately 36.87 degrees (0.643 radians). This gives maps a consistent, neutral perspective. But what if you want to:
- Create a telephoto effect (narrow FOV) for architectural visualization
- Achieve a dramatic wide-angle view (large FOV) for immersive experiences
- Dynamically adjust the visual perspective based on user interaction
The official Mapbox API doesn't expose FOV control—but the internal Transform class does.
What is the Transform Class?
Digging through the Mapbox GL JS source code, I discovered the Transform class—the mathematical heart of Mapbox's rendering system. This 2,800+ line beast handles:
- Camera positioning and orientation
- Projection matrix calculations
- Coordinate system transformations (lat/lng ↔ screen pixels ↔ mercator)
- Zoom level calculations
- Field of view management
The Transform instance lives at map.transform and contains a private _fov property that controls the vertical field of view.
The (Unofficial) Solution
Here's how you can control field of view with a custom function called setFOV.
function setFOV(map, fov) {
// Directly access the internal Transform instance
map.transform._fov = fov;
// Force recalculation of projection matrices
map.transform._calcMatrices();
// Trigger a map repaint
map.triggerRepaint();
}
// Initialize your map
const map = new mapboxgl.Map({
container: 'map-container',
center: [-71.06288, 42.36834],
zoom: 16.85,
pitch: 75.67,
bearing: 141.60
});
map.on('load', () => {
// Apply a custom FOV (in radians)
setFOV(map, 0.8); // Wide angle
// setFOV(map, 0.4); // Telephoto
});
FOV Values Explained
| Radians | FOV effect |
|---|---|
| 0.1 - 0.5 radians (~5-28°): Telephoto effect, compressed perspective | ![]() |
| 0.643 radians (~36.87°): Default Mapbox FOV | ![]() |
| 0.8 - 1.5 radians (~45-86°): Wide angle, dramatic perspective | ![]() |
How It Works Under the Hood
When you modify _fov, three things need to happen:
-
Update the property:
map.transform._fov = newValue -
Recalculate matrices:
map.transform._calcMatrices()recomputes all the projection math including:-
projMatrix- world to clip coordinates -
pixelMatrix- world to screen pixels -
cameraToCenterDistance- camera distance based on FOV
-
-
Trigger repaint:
map.triggerRepaint()forces a redraw with new matrices
The _calcMatrices() method is where the magic happens. From the source:
this.cameraToCenterDistance = 0.5 / Math.tan(this._fov * 0.5) *
this.height * this._pixelsPerMercatorPixel;
This calculates how far the camera should be from the map center based on the FOV, ensuring the perspective projection renders correctly.
Interactive Field of View Controller
Want to let users adjust FOV dynamically? Here's a complete example with a slider you can check on on Codepen.
Why Isn't This a Public API?
You might wonder why Mapbox doesn't officially expose FOV control. A few reasons:
- Complexity: Changing FOV affects tile loading, symbol placement, and many other rendering systems
- Performance: Non-standard FOV values can impact rendering performance
- Consistency: A fixed FOV ensures consistent user experience across applications
- Maintenance: Supporting arbitrary FOV would increase API surface area and testing burden
The Risks
Before you rush to implement this, understand the risks:
- ⚠️ Breaking changes: Internal APIs can change without warning in minor/patch releases
- ⚠️ Unsupported behavior: You may encounter rendering artifacts or unexpected behavior
- ⚠️ No guarantees: Mapbox won't provide support for issues arising from this technique
- ⚠️ Version locked: You'll need to test across Mapbox versions if you update
Alternative: The FreeCamera API
For production use cases involving advanced camera control, check out Mapbox's official FreeCamera API. While it doesn't expose FOV directly, it provides:
- Full camera position control
- Orientation adjustments
- Supported and stable API
- Works with all Mapbox features
Conclusion
Exploring internal APIs like Transform is a fantastic way to understand how sophisticated mapping libraries work under the hood. The FOV control technique shown here opens creative possibilities for enthusiasts and experimental projects.
Just remember: with great power comes great responsibility. Use internal APIs wisely, always have a fallback, and consider this a learning exercise rather than a production strategy.
Tested with Mapbox GL JS v3.18.1. Your mileage may vary with other versions.




Top comments (0)