maptalks.three: putting three.js objects inside a maptalks map
A maptalks layer to render with three.js.
At a glance
- What is it?
- maptalks.three is a maptalks layer that renders with three.js, giving a 2D map engine a WebGL scene that stays in sync with the map camera and projection. It suits GIS developers who need extruded geometry or 3D models on a maptalks map, and its ES6 packaging and version coupling are the two things to check before you adopt it.
- Who is it for?
- Adopt maptalks.three if your application already runs maptalks, needs extruded or modelled geometry on the map, and can ship an ES6 build with a matching three.js version. Do not adopt it if your stack does not already use maptalks, if your deployment target cannot run ES6, or if you need a supported long-term release cadence, since the newest tag is v0.42.2 from 2026-06-02.
- Can I use it commercially?
- Yes. MIT 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 143 days ago.
- What is it written in?
- Mainly HTML, 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
A three.js scene that lives inside a 2D map engine
maptalks is a 2D map engine, and its layer model is the extension point for everything else on the map. maptalks.three uses that extension point to hand a three.js WebGL scene to a layer, so a map can show extruded city models, height-mapped terrain or animated geometry alongside ordinary vector layers.
The mechanism is the interesting part. A layer of this kind is not just a drawing surface; it has to agree with the map about where things are, and about which way the camera faces. The plugin's job is to keep the 3D scene glued to the 2D map's coordinate system as the user pans and zooms.
The repository is small in a way that is easy to miss. The project documentation states that the only source file is index.js, written in ES6 and transpiled by babel, with tests written using mocha and expect.js. The repository layout shows src/, test/, demo/, docs/, types/, a rollup.config.js, a worker-plugin.js and an API.md alongside the Chinese API document API.ZH-CN.md. The demo/ directory holds a long list of standalone HTML examples, including bloom, custom animations, image planes, electric shields and buildings with vertex colours.
For the developer, the practical upshot is that this is a bridge library, not a mapping system. It presumes maptalks and three.js are already part of your application.
prepareToDraw gives you the scene, the camera and the WebGL context
The extension point is a hook called prepareToDraw, which receives the gl context, the three.js scene and the camera. You add your lights, materials and meshes to that scene, and the plugin takes care of the rest.
The browser usage pattern loads three libraries in order, because the plugin must be loaded after maptalks.js and three.js:
<script type="text/javascript" src="https://unpkg.com/[email protected]/build/three.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/maptalks/dist/maptalks.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/maptalks.three/dist/maptalks.three.js"></script>
<script>
var threeLayer = new maptalks.ThreeLayer('t');The layer is then added to the map with map.addLayer(threeLayer), or in the ES module version with threeLayer.addTo(map).
The ES module form is the one most projects will end up with, and it is short:
import * as THREE from 'three';
import * as maptalks from 'maptalks';
import { ThreeLayer } from 'maptalks.three';
const map = new maptalks.Map('map', { /* options */ });
const threeLayer = new ThreeLayer('t');
threeLayer.prepareToDraw = function (gl, scene, camera) {
const light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, -10, -10).normalize();
scene.add(light);
//...
};
threeLayer.addTo(map);Note what the hook signature implies. You receive a scene you own and populate, and a camera that the plugin controls, which is the right split: you build content, the plugin owns the view.
Extruding GeoJSON with toExtrudePolygon
The headline capability is turning map data into 3D geometry. The example in the documentation builds an extruded polygon for every feature of a GeoJSON collection, using a data value as the height:
var material = new THREE.MeshPhongMaterial();
countries.features.forEach(function (g) {
//g is geojson Feature
var num = g.properties.population;
var extrudePolygon=threeLayer.toExtrudePolygon(g, { height: num }, material);
threeLayer.addMesh(extrudePolygon)
});The height is passed per feature, so the extrusion height can be driven by an attribute of the data, which is the usual reason to reach for this: population, height or any other measure becomes building height, and the map becomes an extruded chart rather than a flat one.
The extrusion itself comes from the two runtime dependencies listed in package.json, deyihu-geometry-extrude at 0.1.10 and poly-extrude at ^0.16.0. That matters for two reasons. First, geometry with holes or complex outlines needs a triangulator, and that is what these packages provide. Second, they are runtime dependencies rather than dev dependencies, so they end up in your bundle.
The mesh material is yours to choose, and the demo directory shows the range: MeshPhongMaterial in the doc example, vertex coloured buildings, outline variants, top colour variants, and custom image planes and electric shields. Because the layer hands you a normal three.js scene, none of that is plugin specific.
Packaging changed twice: ES6 UMD and an ES5 fallback
The incompatible changes section is the part to read before you pick a version, because the plugin has changed its packaging twice and both changes can break a working integration.
First, from three.js 128 onwards the default UMD package is ES6. Starting from version 0.16.0 of the plugin, the default UMD package is ES6 as well, to fit the new three.js UMD package change. In other words, the plugin followed three.js into ES6-only distribution.
Second, if your running environment does not support ES6, an ES5 version is provided at maptalks.three.es5.js, and that build requires a three.js version of 127 or lower. So the ES5 path is not just an older build of the plugin, it is a build tied to a three.js line that is well behind the one the project documents elsewhere.
The supported browsers are listed as IE 11, Chrome, Firefox and other modern and mobile browsers that support WebGL. That list and the ES6 default are in tension, and the resolution in practice is that an IE 11 user gets the ES5 bundle with three.js 127, while everyone else gets the modern build.
There is also a migration note from versions up to v0.5.x to v0.6.0 worth knowing: locateCamera was re-implemented and synchronised with the map's projMatrix and viewMatrix, and the model's z position is reversed compared with v0.5.0, so rotation has to be updated for existing models. For three.js 0.94 and older, material side has to be set to BackSide or DoubleSide to render correctly.
Three ways to install, and a note on the source layout
Installation offers the usual three routes. With npm it is a single command, npm install maptalks.three, and working on the plugin itself starts with the dependency install script:
$ npm installOr you can download the build from the dist directory on the gh-pages branch, or load it from the unpkg CDN at https://unpkg.com/maptalks.three/dist/maptalks.three.min.js.
The package.json entry points explain how the module is consumed. main points at dist/maptalks.three.js for CommonJS consumers, module and jsnext:main both point at dist/index.js for bundlers, and types points at dist/index.d.ts, so TypeScript users get declarations from the published package rather than from the src directory. The files field publishes dist/ and src/ only.
Working on the plugin itself needs three scripts. The development workflow uses rollup in watch mode with a dev environment flag, the production build runs the TypeScript compiler first and then rollup, and lint runs eslint over index.js and the src and test trees. The version script rebuilds and stages dist into git, which explains why the built output is committed to the repository, and prepublish runs lint and build again. The docs are built with vitepress.
What the plugin does not do for you
The scope boundary is easy to state, and it is the main risk in adopting this.
maptalks.three renders. It does not manage the 3D asset pipeline, it does not load and simplify city models, and it does not decide what a scene should contain. You write the scene; the plugin renders it in a maptalks layer. For extruded vector data, the helper toExtrudePolygon covers the common case, but anything richer than that is your own three.js code.
Second, it requires WebGL, and the browser support list is tied to that. In an environment without WebGL, or on a virtual machine with software rendering, the map will fall back to two dimensions without the layer and you will need to decide how to degrade.
Third, the version coupling is tight and bidirectional. The plugin must be loaded after both maptalks and three.js, the ES5 build pins three.js to 127 or lower, and the migration notes show that three.js versions around 0.94 to 0.95 changed material side behaviour in a way that changed rendering. This is the reality of a bridge library: it tracks two upstream projects and you inherit the seams.
Fourth, there is no test-driven safety net visible to users. The project says it is tested with mocha and expect.js and carries a karma.config.js and a test/ directory, but the demo/ pages are the primary way new behaviour is demonstrated, so upgrading across a minor version is best done by comparing the demo output as well as the release notes.
MIT licence and a maintenance record with a gap
The licence is MIT, declared in package.json and with a LICENSE file at the repository root. There is no commercial condition, no attribution clause beyond keeping the text, and nothing to negotiate before shipping it in a commercial product.
On maintenance, the repository is not archived and the last push was on 2026-06-02. Recent releases are v0.42.0 on 2026-02-25, v0.42.1 on 2026-06-01 and v0.42.2 on 2026-06-02, and the version in package.json is 0.42.2.
The version number is the important detail for anyone planning to depend on this. The plugin has been below 0.1 for a long time in the numbering sense, and it is still at 0.42.x, so semver offers you no stability guarantee: a 0.x minor bump can carry breaking changes, and the incompatible changes list documents exactly that kind of change at minor version granularity. Pin an exact version.
The development setup is modest: babel for transpilation, rollup for bundling, eslint for linting, mocha and expect.js for tests, and vitepress for the documentation. The continuous integration badge points at CircleCI. Two releases landing a day apart in June 2026 suggest patch-level churn around a specific fix rather than a steady feature cadence, which is consistent with a library that is maintained but no longer moving quickly.
For an evaluation, the sequence is straightforward: read API.md for the layer API, check the incompatible changes section against the three.js version you already ship, and then build one demo from the demo/ directory before committing to the integration.
Editorial conclusion
Adopt maptalks.three if your application already runs maptalks, needs extruded or modelled geometry on the map, and can ship an ES6 build with a matching three.js version. Do not adopt it if your stack does not already use maptalks, if your deployment target cannot run ES6, or if you need a supported long-term release cadence, since the newest tag is v0.42.2 from 2026-06-02. Before you start, check that the three.js version you load matches the plugin, that your maptalks build is loaded first in the script order, and that the extrusion dependencies are acceptable in your bundle, since the package ships poly-extrude and deyihu-geometry-extrude as runtime dependencies.
Frequently asked questions
What is maptalks.three and how does it fit with maptalks and three.js?
It is a maptalks layer that renders with three.js, so a 2D map engine can display WebGL geometry and models. It must be loaded after maptalks.js and three.js in the browser, and it keeps the 3D scene in sync with the map camera and projection.
How do I install maptalks.three?
Install it with npm install maptalks.three, download the build from the dist directory on the gh-pages branch, or load it from the unpkg CDN. The package publishes dist/ and src/, with CommonJS, ES module and TypeScript declaration entry points.
How do I add 3D geometry to a maptalks map?
Create a ThreeLayer, assign a prepareToDraw function that receives the gl context, scene and camera, add your lights and meshes there, and then add the layer to the map with map.addLayer(threeLayer) or threeLayer.addTo(map). The toExtrudePolygon helper builds an extruded mesh from a GeoJSON feature with a given height.
Does maptalks.three work with older browsers such as IE 11?
The project lists IE 11 among the supported browsers, but the default UMD package has been ES6 since version 0.16.0 and three.js 128 and later are ES6 only. An ES5 bundle is published separately and requires a three.js version of 127 or lower.
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/maptalks-maptalks-three)Was this useful?