Switch from ESRI satellite to Carto Voyager map tiles

User wants tiles with place names (Stadt-/Strassennamen) for
orientation while flying. ESRI World Imagery is satellite (no
labels); OSM rejects browser requests without a proper User-Agent
header (which browsers cannot set for img.src).

Carto basemaps is the right alternative:
- Free, no API key required
- CORS enabled (works directly in browser via img.src)
- OSM-derived data, so it has all the same place names
- URL format: {z}/{x}/{y}.png (x before y, unlike ESRI's {z}/{y}/{x})

Voyager style chosen for good legibility of place names and
streets. Other Carto styles (light_all, dry_lite, etc.) are also
available; just change the URL path.

Swapped tileX/tileY in the fetch URL to match Carto's {x}/{y}
order (ESRI used {y}/{x}).

Attribution: (c) OpenStreetMap contributors (c) CARTO.
This commit is contained in:
Richard Zink committed 2026-10-08 08:35:21 +02:00
1 parent 9191bb5776
commit 262d308a5a
1 file changed
+5 -2
+5 -2
View File
@@ -282,7 +282,9 @@ function init(canvas) {
// 1 world unit = 1 tile at zoom 11 (~13 km). The shader maps // 1 world unit = 1 tile at zoom 11 (~13 km). The shader maps
// (hitPoint - uGroundCenter) / uGroundSize + 0.5 to UV, so the // (hitPoint - uGroundCenter) / uGroundSize + 0.5 to UV, so the
// mosaic centre always corresponds to UV (0.5, 0.5). // mosaic centre always corresponds to UV (0.5, 0.5).
var GROUND_TILE_URL = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/'; // Tile source: Carto basemaps Voyager style (with place names).
// Free, CORS-enabled, OSM-derived. URL format {z}/{x}/{y}.png.
var GROUND_TILE_URL = 'https://a.basemaps.cartocdn.com/voyager/';
var GROUND_TILE_Z = 11; var GROUND_TILE_Z = 11;
var GROUND_TILE_SIZE = 256; var GROUND_TILE_SIZE = 256;
// Fetch direction: which way the tile corridor is oriented. // Fetch direction: which way the tile corridor is oriented.
@@ -316,7 +318,8 @@ function fetchTileImage(tileX, tileY) {
img.crossOrigin = 'anonymous'; img.crossOrigin = 'anonymous';
img.onload = function() { resolve(img); }; img.onload = function() { resolve(img); };
img.onerror = function() { reject(new Error('tile fetch failed')); }; img.onerror = function() { reject(new Error('tile fetch failed')); };
img.src = GROUND_TILE_URL + GROUND_TILE_Z + '/' + tileY + '/' + tileX; // Carto/OSM-style format: {z}/{x}/{y}.png
img.src = GROUND_TILE_URL + GROUND_TILE_Z + '/' + tileX + '/' + tileY;
}); });
} }