ol-cesium: OpenLayers and CesiumJS in the same application
OpenLayers - Cesium integration
At a glance
- What is it?
- ol-cesium is a TypeScript library that makes an OpenLayers map and a CesiumJS globe describe the same data, so you can switch between a flat map and a globe without rebuilding your layers, your selection or your camera. The npm package is `olcs`, it is BSD-2 licensed, and the README is candid about the parts that are not supported yet.
- Who is it for?
- Adopt ol-cesium if your application already renders with OpenLayers and you want a 3D globe view without rewriting the application around CesiumJS, especially if you need the two views to stay in step. Do not adopt it expecting full OpenLayers semantics in 3D, because the README states that OpenLayers interactions are not supported in 3D and that unmanaged layers are not discoverable, so plain layers and the synchronisation machinery are the supported path.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three ways to use it, and the one global you have to provide
ol-cesium is described as an open source JavaScript library for making OpenLayers and CesiumJS work together in the same application, and the README splits that into three use cases. You can add 3D to an existing OpenLayers map, you can extend CesiumJS with new capabilities, and you can cherry-pick the pieces you need. The third option is unusual and worth explaining, because it is the most flexible. Specific low level functionalities can be imported individually from the library rather than taken as a whole synchronisation layer, for example a helper that produces a Google Maps style rotating effect, or a converter that turns an OpenLayers vector layer into CesiumJS primitives, or a synchroniser that keeps a whole layer in step. The integration point is a global. CesiumJS is accessed through the global `window.Cesium` object, and the README is explicit that you can use any version of CesiumJS, the latest upstream or a fork, as long as you provide it that way, with a script tag as the example. The npm package is called `olcs`, which is worth knowing because the repository name and the import name differ.
What synchronisation actually covers
The feature list is about keeping the two views honest, and the items are the ones that break in practice if you do not handle them. Switching smoothly between 2D and 3D and synchronising covers the map context, meaning the bounding box and the zoom level, so a zoom in the 2D map puts the globe in the right place. Raster data sources are synchronised, so an imagery layer shows in both. Vector data sources are synchronised in 2D and in 3D, which is the hard case, since the same features have to become CesiumJS primitives. Map selection is synchronised, so the selected items are the same in both views, and there are animated transitions between the map and the globe view, which is what keeps a toggle from feeling like a page reload. The library is also configurable and extensible in two specific ways: you can load Cesium lazily or eagerly, and you can limit Cesium's resource consumption with idle detection, which matters when the globe is the expensive half of the application.
The tutorial is four steps and a script tag
The integration path in the README is short, and the interesting part is that the OpenLayers map is the thing you already have. You create or reuse an OpenLayers map, pass it to the OL-Cesium constructor, and the library creates and synchronises a 3D globe from your layers and data.
// Create an OpenLayers map or start from an existing one.
import Map from 'ol/Map.js';
const ol2dMap = new Map({
...
});
ol2dMap.addLayer(....)// Pass the map to the OL-Cesium constructor
// OL-Cesium will create and synchronize a 3D CesiumJs globe from your layers and data.
import OLCesium from 'olcs';
const ol3d = new OLCesium({map: ol2dMap});ol3d.setEnabled(true); // switch to 3D - show the globe
ol3d.setEnabled(false); // switch to 2D - show the mapCesiumJS itself is loaded by you, through the global, and the README shows the script tag for a specific CesiumJS release. You then build with your preferred bundler, and the note that any version of CesiumJS works, including a fork, is there because some organisations carry their own build. There is one projection catch worth planning around, since synchronising maps in projections other than EPSG:4326 and EPSG:3857 requires two datasets, and the customProj example exists to show how that is done.
Extending Cesium the other way round
The mirror image of the integration is also supported. If your application starts from a CesiumJS globe rather than from an OpenLayers map, the library can add OpenLayers capabilities to it. The README shows adding an OpenLayers imagery provider to the viewer's imagery layers, and adding a Mapbox MVT imagery provider, which does client side rendering of vector tiles, and both are imported from `olcs`. There is also a lower level route with the feature converter, which turns an OpenLayers vector layer into CesiumJS primitives and hands back a primitive collection you can add to the scene, and a synchroniser that keeps a layer in step for you. The honest caveat sits right next to these examples. The README says this is a bit limited at the moment, and lists the ideas that would make it complete, namely client side reprojection, full client side MVT rendering, GeoTIFF rendering, and in effect any feature available in OpenLayers. If your CesiumJS application needs features from that list, the current library will not give them to you.
Configuration lives in a properties document, not in the code
The library is configured through properties, and the README points at a dedicated document, `PROPERTIES.MD`, for the specifics, plus the generated API documentation. That split is a sign of a library with a real surface area, since the properties file is where the switches live and the API doc is where the objects are described. The two capabilities mentioned in the feature list are the ones you will look up first. Lazy versus eager loading of Cesium decides whether the globe's code and data are fetched when the page loads or when the user first switches to 3D, which is a real choice between startup time and a delay at the moment of the toggle. Idle detection limits the resource consumption of the globe, which is the second half of the same problem, since a CesiumJS viewer left enabled in the background is a persistent cost. For the cherry-picking use case, the README invites issues if you think a low level feature should be surfaced, which is a reasonable way to grow a library that exposes a lot at the module level.
The limitations are stated, with issue numbers
The README has a section on the limitations that come from OpenLayers itself, and it links the two issues so you can see the discussion. The first is that OpenLayers unmanaged layers are not discoverable and as a consequence are not supported, so plain layers should be used instead of synchronisation being managed manually. The second is that OpenLayers interactions are not supported in 3D, which is a sharper constraint than it first appears, since a click handler, a drag or a hover interaction written against OpenLayers simply does not exist in the globe view. Both are consequences of the two libraries having different interaction models rather than of unfinished work in ol-cesium, which is the sort of limitation you plan around rather than wait for. Add the projection requirement of two datasets for non-standard projections and the feature gap in the Cesium extension direction, and you have a fair picture of where the library is strong, which is the OpenLayers first, globe second case, and where it is thin.
How the project is built and tested
The package is modern TypeScript with a single source entry point, `src/olcs.ts`, compiled to `lib/olcs.js` with type declarations, and the exports map publishes the package root, the stylesheet, and the per module sources and outputs, which is what makes the cherry-picking use case work at the package level. The test script runs the Node test runner with source maps and a tsx loader over the test files in `src/olcs`, so the tests run against TypeScript sources without a separate build step, and there is a separate `typecheck` script and a `checks` script that runs lint and type checking together. Documentation is generated with typedoc into an `apidoc` directory, using modifier tags to mark the public API, and the examples are built with vite, with a `copy-static-dist` step that assembles a runnable example directory including the Cesium builds and a `copy-rawjs-sandbox` step that produces a raw script tag version, which is a detail that tells you the examples are tested in both bundler and no-bundler setups. The repository also carries `CHANGES.md`, `RELEASE.md`, `CONTRIBUTING.md`, a `buildtools/` directory, a `gh-pages-template` for the documentation site and an `eslint.config.js`. The licence is BSD-2-Clause, and the release history shows steady maintenance, with 2.23.0 in April 2026, 2.23.1 in August 2026 and a last push in October 2026.
Editorial conclusion
Adopt ol-cesium if your application already renders with OpenLayers and you want a 3D globe view without rewriting the application around CesiumJS, especially if you need the two views to stay in step. Do not adopt it expecting full OpenLayers semantics in 3D, because the README states that OpenLayers interactions are not supported in 3D and that unmanaged layers are not discoverable, so plain layers and the synchronisation machinery are the supported path. Before you design around it, check the projection requirement, since a map in a projection other than EPSG:4326 or EPSG:3857 needs two datasets, and check that the CesiumJS build you want to use is available as a `window.Cesium` global. The licence is BSD-2-Clause, the current release is 2.23.1 from 2026-08-12, and the last push was on 2026-10-19.
Frequently asked questions
What does ol-cesium actually do?
It makes OpenLayers and CesiumJS work together in the same application. Switching between 2D and 3D synchronises the map context, that is the bounding box and zoom level, raster data sources, vector data sources in both views, the map selection, and it animates the transition between map and globe view.
How do I add 3D to an existing OpenLayers map?
Create or reuse your OpenLayers map, import OLCesium from `olcs`, construct it with the map, for example `new OLCesium({map: ol2dMap})`, and then call `setEnabled(true)` to show the globe and `setEnabled(false)` to go back to the map. CesiumJS is loaded by you as the `window.Cesium` global, and any version or fork works.
What are the known limitations of ol-cesium?
OpenLayers unmanaged layers are not discoverable and therefore not supported, so plain layers should be used, and OpenLayers interactions are not supported in 3D. Maps in projections other than EPSG:4326 and EPSG:3857 need two datasets, and the README notes the Cesium extension direction is limited, with client side reprojection, full client side MVT rendering and GeoTIFF rendering listed as future work.
What is the npm package name for ol-cesium?
The package is published as `olcs`, while the repository is openlayers/ol-cesium. The library is BSD-2-Clause licensed, and the README documents configuration through properties in PROPERTIES.MD and the generated API documentation.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/openlayers-ol-cesium)Was this useful?