Frontend Development 19 min read

Building Tile‑Style Large‑Screen Maps with mapbox‑gl, maplibre‑gl, and Tianditu

This tutorial explains the differences between mapbox‑gl and maplibre‑gl, shows how to obtain and use Tianditu tile services, and provides step‑by‑step code for creating a tile‑style large‑screen map with 2.5D view, custom layers, and business data overlays.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Building Tile‑Style Large‑Screen Maps with mapbox‑gl, maplibre‑gl, and Tianditu

What You Will Learn

Understand the strengths and limitations of mapbox-gl and maplibre-gl .

Learn how to use the official Tianditu map platform.

Implement a practical tile‑style map project.

Metaphor About the Hammer

Just as a person holding a hammer sees everything as a nail, the author treats mapbox-gl / maplibre-gl as a "multi‑function hammer" for large‑screen map development.

1. Choosing a Map Engine

The GIS world is dominated by Mapbox’s vector‑tile standard (MAPBOX VECTOR TILE SPECIFICATION). mapbox-gl is the official rendering engine, offering features such as projection support, layer stacking, GeoJSON, images, text, custom styles, 2.5D rotation, 3D models, DOM‑based HTML overlays, and WebGL rendering.

Key advantages are its 2.5D view and 3D model support, which surpass OpenLayers and Leaflet. However, it has drawbacks: no support for underground pipe‑network visualization, weaker 3D compared to Cesium, and limited openness.

Since version 2, mapbox-gl-js requires an access token tied to an international credit card, making it less accessible for many developers.

1.2 Why Switch to maplibre‑gl?

maplibre-gl is a fully open‑source fork of mapbox-gl that does not require an access token. It retains the powerful capabilities of mapbox-gl while being truly open.

1.3 Simple Selection Principle

If you need Mapbox’s official tile service, use mapbox-gl .

If you only need the engine’s capabilities without Mapbox tiles, choose the open maplibre-gl .

2. How Large‑Screen Maps Are Usually Built

Two common visual styles exist for big‑screen maps: a wireframe style and a tile style. The choice depends on business requirements—coarse‑grained data favors wireframe, while precise geographic detail requires tile style.

3. Using Tianditu as an Online Tile Service

Tianditu, provided by the National Basic Geographic Information Center, offers free, authoritative map tiles. After registering as an individual developer, you obtain a key used in tile URLs.

// Global variable to store the key (do NOT expose it in production)
window.MY_KEY = '88******************2030'

Tile URLs are constructed like:

https://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=${MY_KEY}

4. Rendering the Map with maplibre‑gl

4.1 Install the Engine

Via Yarn:

yarn add maplibre-gl@latest

Or via CDN:

<script src='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.js'></script>
<link href='https://unpkg.com/maplibre-gl@latest/dist/maplibre-gl.css' rel='stylesheet' />

4.2 Initialize a Tianditu Tile Map

<template>
  <div ref="mapEl" class="map"></div>
</template>
<script setup>
import mapboxgl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { onMounted, ref } from 'vue';
const mapEl = ref(null);
const initOption = {
  style: {
    version: 8,
    id: '43f36e14-e3f5-43c1-84c0-50a9c80dc5c7',
    sources: {
      'tdt-vec': {
        type: 'raster',
        tiles: [`https://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=${MY_KEY}`],
        tileSize: 256
      }
    },
    layers: [{
      id: 'tdt-tiles-layer',
      type: 'raster',
      source: 'tdt-vec'
    }]
  }
};
onMounted(() => {
  const map = new mapboxgl.Map({
    container: mapEl.value,
    ...initOption
  });
});
</script>
<style scoped>
.map { width: 600px; height: 300px; }
</style>

This creates a Mercator‑projected, tile‑style 2D map with 2.5D tilt support.

4.3 Adding Layers and Sources

In the Mapbox/Maplibre model, a map consists of sources (data) and layers (visual representation). Adding a feature follows two steps:

// step 1: add a source
map.addSource('my-source', { type: 'geojson', data: myGeoJSON });
// step 2: add a layer
map.addLayer({ id: 'my-layer', type: 'fill', source: 'my-source', paint: { 'fill-color': 'red', 'fill-opacity': 0.5 } });

4.4 Adding Tianditu Annotation Tiles

"sources": {
  "tdt-cva": {
    "type": "raster",
    "tiles": [
      `https://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=${MY_KEY}`
    ],
    "tileSize": 256
  }
},
"layers": [{
  "id": "tdt-cva-layer",
  "type": "raster",
  "source": "tdt-cva"
}]

4.5 Fine‑Tuning Map Appearance

Adjust raster layer paint properties to match a dark UI theme:

{
  "id": "tdt-tiles-layer",
  "type": "raster",
  "source": "tdt-vec",
  "paint": {
    "raster-brightness-max": 0.7,
    "raster-brightness-min": 0.3,
    "raster-hue-rotate": 20,
    "raster-saturation": 0.7
  }
}

Alternatively, switch to Tianditu imagery tiles by changing the source URLs.

5. Loading Business Data

5.1 Rendering Polygon Areas

map.on('style.load', () => {
  map.addSource('geojson-area-source', {
    type: 'geojson',
    data: geojsonArea
  });
  map.addLayer({
    id: 'geojson-area-layer',
    type: 'fill',
    source: 'geojson-area-source',
    paint: { 'fill-color': 'red', 'fill-opacity': 0.5 }
  });
});

5.2 Adding Icons and Labels

First load custom images:

const loadImages = async (imgs) => {
  await Promise.all(Object.entries(imgs).map(([key, url]) =>
    new Promise((resolve) => {
      map.loadImage(url, (error, res) => {
        if (error) throw error;
        map.addImage(key, res);
        resolve(res);
      });
    })
  ));
};

Then add a GeoJSON source for the points and two layers – one for the icons and one for the text labels:

// add source
map.addSource('boys-source', { type: 'geojson', data: boys });
// icon layer
map.addLayer({
  id: 'boys-icon-layer',
  type: 'symbol',
  source: 'boys-source',
  layout: {
    'icon-image': '{icon}',
    'icon-size': 0.2,
    'icon-anchor': 'center',
    'icon-rotation-alignment': 'viewport',
    'icon-allow-overlap': true
  }
});
// label layer
map.addLayer({
  id: 'boys-name-layer',
  type: 'symbol',
  source: 'boys-source',
  layout: {
    'text-field': '{name}',
    'text-size': 14,
    'text-offset': [0, 2.4],
    'text-allow-overlap': true
  },
  paint: { 'text-color': 'white' }
});

6. Conclusion

The article covered:

The usage scope of mapbox-gl and maplibre-gl .

How to obtain and apply Tianditu tile services.

Practical implementations of several business scenarios, including tile‑style maps, annotation layers, visual adjustments, and dynamic data overlays.

With this knowledge, developing tile‑style large‑screen maps should no longer be a hurdle. The next chapter will explore wireframe‑style map development.

JavaScriptWeb GISTianditumapbox-glmaplibre-gl
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.