Protomaps Basemap karoları

Tüm Protomaps Basemap, yakınlaştırma 0 ile 15 arası, düz HTTP üzerinden tek bir PMTiles arşivi olarak sunulur. Herhangi bir PMTiles istemcisini bu URL'ye yönlendirin, çalışır.

https://tiles.jasontally.com/basemap.pmtiles

Engellenmiş bir OpenStreetMap karosu veya tile.openstreetmap.org adresinden 403 hatası mı alıyorsunuz? Buradan başlayın.

Deneyin

Aynı arşiv üç stilde. Stili değiştirdiğinizde yüklü karolar yerinde kalır, bu yüzden geçiş anlıktır.

z0

Kendinizinkini oluşturun

Bir rengi değiştirin veya bir katmanı kapatın, harita anında güncellenir. Ardından kendiniz barındırabileceğiniz normal bir MapLibre stili olan stil JSON'unu kopyalayın. Bu karolara işaret ettiği için nereye koyarsanız koyun çalışmaya devam eder.

Kullanın

Arşiv HTTP aralık isteklerini destekler, bu nedenle her PMTiles istemcisi onu okuyabilir.

Bir. Sayfaya bir harita koyun

Bu dosyayı kopyalayın. Tüm örnek bundan ibarettir: üç etiket, bir stil URL'si, bir harita. Her iki kütüphane de sabit sürümlüdür ve BSD-3-Clause lisanslıdır; bir CDN kullanmak istemiyorsanız aynı dosyalar bu sunucudan da sunulur.

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Basemap</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.css">
  <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.24.0/dist/maplibre-gl.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/pmtiles@3.2.1/dist/pmtiles.js"></script>
  <style>html, body, #map { margin: 0; height: 100%; }</style>
</head>
<body>
  <div id="map"></div>
  <script>
    // Teach MapLibre how to read a PMTiles archive.
    const protocol = new pmtiles.Protocol();
    maplibregl.addProtocol("pmtiles", protocol.tile);

    new maplibregl.Map({
      container: "map",
      style: "https://tiles.jasontally.com/styles/light.json",
      center: [2.35, 48.85],   // Paris
      zoom: 4
    });
  </script>
</body>
</html>

İki. Mevcut stilinizdeki karoları değiştirin

Her MapLibre stili karolarını bir kaynaktan okur. Bu karoları kullanmak için o tek url değerini değiştirin. Stildeki başka hiçbir şey değişmez.

  "sources": {
    "protomaps": {
      "type": "vector",
-     "url": "pmtiles://https://demo-bucket.protomaps.com/v4.pmtiles",
+     "url": "pmtiles://https://tiles.jasontally.com/basemap.pmtiles",
      "attribution": "<a href=\"https://www.openstreetmap.org/copyright\">&copy; OpenStreetMap contributors</a>"
    }
  }

Veya bunu kod içinde yapın; stil kontrol etmediğiniz bir sunucudan geliyorsa bu yöntem işe yarar:

// Rewrite every PMTiles source in a style to point at these tiles.
const style = await (await fetch("https://your-server/style.json")).json();

for (const source of Object.values(style.sources)) {
  if (source.url?.startsWith("pmtiles://")) {
    source.url = "pmtiles://https://tiles.jasontally.com/basemap.pmtiles";
  }
}

new maplibregl.Map({ container: "map", style, center: [2.35, 48.85], zoom: 4 });

Üç. Oluşturduğunuz stili nereye koymalısınız

Yukarıdaki oluşturucuda bulunan Stil JSON'u düğmesi, bu haritanın şu anda çizdiği stili düzenlemeler dahil açar ve iletişim kutusunda bir kopyalama düğmesi vardır. Size verdiğini kullanmanın iki yolu vardır ve ikisi de sıradan web sayfalarıdır.

Sayfanızın yanına bir dosya olarak kaydedin ve bu sunucudaki üç stilin kullanıldığı gibi style ayarını ona yönlendirin. Stil size aitse ve sitenizle birlikte değişiyorsa seçeceğiniz yöntem budur:

// Save the copied JSON as my-basemap.json beside this file.
new maplibregl.Map({
  container: "map",
  style: "my-basemap.json",           // relative, same origin
  center: [2.35, 48.85],
  zoom: 4
});

Veya HTML içinde tutun; böylece taşınacak tek bir dosya olur ve ayrıca barındırılacak bir şey kalmaz. Stil aynıdır, yalnızca bulunduğu yer farklıdır:

// The copied JSON, pasted straight into the page.
const myStyle = {
  "version": 8,
  "name": "Protomaps Basemap — custom",
  "glyphs": "https://tiles.jasontally.com/font/{fontstack}/{range}.pbf",
  "sprite": "https://tiles.jasontally.com/sprites/v4/light",
  "sources": { /* ... as copied ... */ },
  "layers":  [ /* ... as copied ... */ ]
};

new maplibregl.Map({ container: "map", style: myStyle, zoom: 4 });

glyphs ve sprite satırlarını olduğu gibi bırakın. Etiketleri ve simgeleri çizen bunlardır ve bu sunucuya işaret ederler; böylece kendi sayfanıza yapıştırdığınız bir stil, onu nereden sunarsanız sunun çalışmaya devam eder. Bu sunucuya hiç bağımlı olmamayı tercih ediyorsanız bunları protomaps.github.io/basemaps-assets adresine yönlendirin.

Değiştirmeden önce kontrol etmeniz gereken bir şey. Bu arşiv Protomaps şeması v3 kullanır. Farklı bir şema için yazılmış bir stil yüklenir ancak kaynak katman adları eşleşmediği için hiçbir şey çizmez. Dokuz katman adı ve kopyalayabileceğiniz hazır bir v3 stili aşağıda listelenmiştir.

Dört. Yazı tipleri, sprite'lar ve kütüphaneler

Bir harita; karolar, metin için bir glyphs URL'si, isteğe bağlı olarak simgeler için bir sprite URL'si ve bunları çizecek kütüphanelerden oluşur. Bunların tamamı burada, her birinin beklediği yollarda bulunur; böylece isterseniz bir harita tek bir sunucu adından gelebilir.

NeBuradaki URLLisans

MapLibre ve PMTiles dosyaları hem jsDelivr'da hem de buradadır. İki URL de çalışır.

Son satır bu sayfa tarafından kullanılmaz. Geçişin tek bir betik etiketiyle yapılabilmesi için burada yayınlanan Leaflet vektör çizicisidir. Leaflet'in kendisi kendi CDN'inde kalır.

İki yazı tipi yığını, Noto Sans Regular ve Noto Sans Medium, MapLibre'nin istediği 256 aralığa, her seferinde 256 kod noktası olacak şekilde bölünmüştür. Yalnızca Latin olanlar değil, 256 aralığın tamamı yayınlanır: Protomaps coğrafi öğeleri yerel adlarıyla etiketler, bu nedenle Tokyo veya Kahire on binlerce aralığa ihtiyaç duyar. Yalnızca İngilizce bir haritanın kullandıklarını yayınlarsanız bu etiketler nedenini belirten hiçbir hata vermeden kaybolur.

Her üst kaynak çeşidi için birer tane olmak üzere, 1x ve 2x çözünürlükte beş sprite sayfası. Aşağıdaki stiller simgeleri bunlardan çizer, bu yüzden bunlar indirilir. Kendi stilinizde yerleşim noktaları, otoyol levhaları veya ilgi noktaları istiyorsanız, sprite ayarını kendi çeşidinize ait olana yönlendirin. Bir sayfadaki simge adları kendi light.json dosyasında listelenir.

Harita ne çizer ve her şey nereden gelir

Her katman bu arşivdeki dokuz kaynak katmandan biridir, bu nedenle buradaki hiçbir şey ikinci bir arşive ihtiyaç duymaz. İkisi özellikle belirtilmeye değerdir, çünkü ikisi de eksik değilken eksikmiş gibi görünür:

KatmanGeldiği yerBu derlemede var mı?
Şekiller, yollar, binalar, su, araziearth, landcover, landuse, water, roads, buildingsevet
Yer, yol ve su adlarıaynı katmanlardaki name alanıevet
İlgi noktası simgeleri, yerleşim noktalarıpois.kind, places ve spriteevet
Yol numaralandırma levhalarıroads.shield_texthayır. Sunulan derlemede bu alan yok
Kapı numaralarıbuildings.kind=address ve buildings.addr_housenumberhayır, aynı nedenden

Ayrı bir adres arşivi ve indirilecek bir adres katmanı yoktur. Üst kaynak proje, adres noktalarını buildings katmanının içine, kind=address ve addr_housenumber değerine sahip öğeler olarak yerleştirir. Bu alan, bu haritanın sunduğu derlemeden daha sonraki bir Protomaps derlemesinde geldi; bu nedenle kapı numarası katmanı hazırdır ve bir sonraki aylık yenileme onları getirdiğinde kendiliğinden açılır. Aynı durum levha metni için de geçerlidir: mevcut derleme, bir yol numarasının ne olduğunu değil kaç karakter olduğunu belirten shield_text_length alanını taşır; bu yüzden ondan çizilen bir levha her otoyolda boş bir şekil olur.

Kendi katmanınızı yazmak ve renklendirmek

Bir katman; bir filtre, bir yakınlaştırma düzeyi, bir şekil ve bir renkten oluşur. Filtredeki iki şey herkesi yanıltır ve ikisi de hata vermeden başarısız olur:

Bir yol, adı ve çizgiyi kapatmak için bir anahtar:

{
  "id": "road-major",
  "type": "line",
  "source": "protomaps",
  "source-layer": "roads",            // one of the nine
  "minzoom": 4,                                  // not drawn below this
  "filter": ["==", ["get", "kind"], "major_road"],
  "layout": {
    "line-cap": "round",
    "visibility": "visible"          // "none" to hide it
  },
  "paint": {
    "line-color": "#f7c44d",          // any CSS colour
    "line-width": ["interpolate", ["linear"], ["zoom"], 4, 1.7, 12, 6]
  }
}

Bir ad, arkasında hale olan veya olmayan, name alanını okuyan bir sembol katmanıdır. Eksik bir glyph sessizce geçilir, bu nedenle istediğiniz yazı tipi yığını bu sunucudaki ikisinden biri olmalıdır:

{
  "id": "road-label-major",
  "type": "symbol",
  "source": "protomaps",
  "source-layer": "roads",
  "minzoom": 11,
  "layout": {
    "text-field": ["coalesce", ["get", "name:en"], ["get", "name"]],
    "text-font": ["Noto Sans Medium"],  // or Noto Sans Regular
    "text-size": 10,
    "symbol-placement": "line"       // follow the road
  },
  "paint": {
    "text-color": "#2b2a26",
    "text-halo-color": "#ffffff",
    "text-halo-width": 1.1
  }
}

Hiçbir şey çizmeyen bir katman hata sayılmaz ve MapLibre hangi kontrolün başarısız olduğunu söylemez. Sizinki boşsa şu sırayla kontrol edin: alan adı, katmanın minzoom değeri, yazı tipi yığını, ardından sayfanın kendi light.json dosyasındaki simge adı.

Glyph'lerini demotiles.maplibre.org adresine yönlendiren bir stiliniz varsa, tüm değişiklik o sunucu adını değiştirmekten ibarettir. Dosya yolu bilinçli olarak aynı tutulmuştur.

"glyphs": "https://tiles.jasontally.com/font/{fontstack}/{range}.pbf",
"sprite": "https://tiles.jasontally.com/sprites/v4/light"

// before, in a style you already have
- "glyphs": "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",
+ "glyphs": "https://tiles.jasontally.com/font/{fontstack}/{range}.pbf",

Bir stil yukarıdaki ikisinden biri olmayan bir yazı tipi yığını isterse onun için hiçbir şey çizilmez. Protomaps'in kendi stilleri kalın metin için Noto Sans Medium kullanır; bu sette Noto Sans Bold yoktur, bu yüzden onu isteyen bir stil tüm etiketleri sessizce kaybeder.

Hangi sunucu daha hızlıdır ve bu konuda ne karar verildi. Varsayılmadı, ölçüldü: tek bağlantıda, her seferinde bir tane olmak üzere sırayla serpiştirilmiş istekler, ilk üç örnek atıldı, ilk bayt süresi aktarım süresinden ayrıldı. Bu testte bir CDN bu dosyaların her biri için 10 ila 45 ms daha erken yanıt verdi; bu da %15 kuralının tamamını karşılar ve örneklerin açıkça aştığı bir farktır. Kütüphaneler bu nedenle jsDelivr'dan yüklenir.

Aynı ölçüm bir CDN'in yaklaşık 10 ms daha erken yanıt vereceğini söylese de yazı tipleri ve sprite'lar buradan sunulur. Bu bir ölçüm değil, bir karardır. Tek bir sunucu adından gelen bir harita, başka birinin sunucusu çöktüğünde bozulmaz ve çalışmayan bir glyph sunucusu etiketsiz bir harita demektir. 10 ms kazancı tercih ederseniz glyphs ayarını protomaps.github.io/basemaps-assets/fonts adresine yönlendirin, aynı yolla çalışır. Bunlar bir okurun bir şehirden aldığı sayılardır ve karşılaştırmayı yeniden çalıştırmak tek bir komuttur.

Beş. Leaflet hakkında

Leaflet'in L.tileLayer işlevi resim çizer; bunlar ise vektör karolardır. Bir Leaflet haritası yine de bunları kullanabilir ve her iki yöntem de işaretçilerinizi, açılır pencerelerinizi ve kontrollerinizi korur. Her iki geçiş yöntemi de OpenStreetMap karolarından geçiş bölümündedir.

Altı. Arşivi PMTiles kütüphanesiyle okuyun

Harita yok, yalnızca veri. Betikler, testler ve resim olmayan her şey için kullanışlıdır.

import { PMTiles, FetchSource } from "pmtiles";

const archive = new PMTiles(new FetchSource("https://tiles.jasontally.com/basemap.pmtiles"));

const header = await archive.getHeader();
console.log(header.minZoom, header.maxZoom);        // 0 15
console.log(header.numAddressedTiles);              // 1431655765

const metadata = await archive.getMetadata();
console.log(metadata.name);                          // "Protomaps Basemap"

const tile = await archive.getZxy(3, 4, 2);          // z, x, y
console.log(tile.data.byteLength);

İki sınıfa dikkat edin. FetchSource HTTP üzerinden bayt okuyucudur ve PMTiles onun üzerinde duran ve biçimi anlayan okuyucudur. FileSource, FetchSource sınıfının yerel dosya karşılığıdır; bir URL dizgesi verildiğinde çalışmaz.

Arşiv canlı bir akış değil, anlık bir görüntüdür. Zamanlama bilgisi Bu ne kadar güncel? bölümündedir.

OpenStreetMap karolarından geçiş

Karo kullanım politikası engeli, 403 hatası ve bunlar hakkında ne yapılacağı. Anahtar yok, kota yok.

Harita neden bir engel görüntüsü gösteriyor

App is not following the tile usage policy of OpenStreetMap’s volunteer-run servers

General block: app is not following the tile usage policy of openstreetmap volunteer-run servers

403 Forbidden — tile.openstreetmap.org

Karo sunucuları, karo kullanım politikası kapsamında harita yerine o görüntüyü bilerek gönderdi. Bu bir arıza değildir ve URL'yi düzeltmek bunu ortadan kaldırmaz.

İnsanların ilk denedikleri:

Ofisler, okullar, VPN'ler ve mobil ağlar aynı adresi paylaşır ve engeller uygulamaların yanı sıra adreslere de uygulanır. Kendi tarafınızdan hangisine takıldığınızı anlayamazsınız.

Bu yüzden o sunuculara istek göndermeyi bırakın. Onlardan ayrılmanın üç yolu vardır.

Leaflet'te kalın

protomaps-leaflet, Leaflet içinde vektör karolar çizer. Arşivi kendisi okur ve kendisini normal bir katman olarak ekler; böylece işaretçiler, açılır pencereler, GeoJSON ve kontroller oldukları yerde kalır. Bu arşivle test edilmiş bir kopyası buradadır: https://tiles.jasontally.com/vendor/protomaps-leaflet.js.

Önce:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>

<script>
  const map = L.map("map").setView([48.85, 2.35], 12);

  L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
    maxZoom: 19,
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  }).addTo(map);
</script>

Sonra:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
+ <script src="https://tiles.jasontally.com/vendor/protomaps-leaflet.js"></script>

<script>
  const map = L.map("map").setView([48.85, 2.35], 12);

-  L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { ... }).addTo(map);
+  protomapsL.leafletLayer({
+    url: "https://tiles.jasontally.com/basemap.pmtiles",
+    flavor: "light",
+    lang: "en"
+  }).addTo(map);
</script>

protomaps-leaflet üst kaynakta bakım modundadır: yeni özellikler değil, yalnızca düzeltmeler alır. Mevcut bir Leaflet uygulaması için uygundur. Yeni çalışmalar MapLibre GL ile başlamalıdır.

Leaflet'te kalın, MapLibre ile çizin

@maplibre/maplibre-gl-leaflet, Leaflet'in karo bölmesine bir MapLibre haritası yerleştirir. Leaflet olarak kalan bir uygulamada yukarıdaki stillerden birini veya arazi ve kabartma gölgelendirmesini istediğinizde bunu kullanın.

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<link rel="stylesheet" href="https://tiles.jasontally.com/vendor/maplibre-gl.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://tiles.jasontally.com/vendor/maplibre-gl.js"></script>
<script src="https://tiles.jasontally.com/vendor/pmtiles.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@maplibre/maplibre-gl-leaflet@0.1.4/dist/leaflet-maplibre-gl.js"></script>

<script>
  // The style's source is pmtiles://, so MapLibre needs the protocol first.
  maplibregl.addProtocol("pmtiles", new pmtiles.Protocol().tile);

  const map = L.map("map", { minZoom: 1 }).setView([48.85, 2.35], 12);

  const gl = L.maplibreGL({
    style: "https://tiles.jasontally.com/styles/light.json"
  }).addTo(map);

  // gl.getMaplibreMap() is the MapLibre map, for sources and layers.
</script>

MapLibre GL'ye geçin

Tek kütüphane, bağdaştırıcı yok ve yukarıdaki stiller olduğu gibi çalışır. Tam sayfa Bir. Sayfaya bir harita koyun bölümündedir. Geçiş çoğunlukla koordinat sırasını ters çevirmekten ibarettir:

LeafletMapLibre GL
L.map("map").setView([lat, lng], z)new maplibregl.Map({ container: "map", center: [lng, lat], zoom: z })
L.tileLayer(url).addTo(map)vektör kaynağı olan bir stil; yukarıya bakın
L.marker([lat, lng]).bindPopup(html)new maplibregl.Marker().setLngLat([lng, lat]).setPopup(new maplibregl.Popup().setHTML(html))
L.geoJSON(data)addSource(id, { type: "geojson", data }), ardından addLayer
L.control.scale()new maplibregl.ScaleControl()
map.invalidateSize()map.resize()

setView([lat, lng]) önce enlemi alır; her MapLibre çağrısı ise [lng, lat] alır. Yanlış yarımkürede çıkan bir haritanın nedeni karolar değil budur. Stil yüklenmeden önce eklenen kaynaklar ve katmanlar hata vermeden yok sayılır, bu nedenle bunları map.on("load", …) içinde ekleyin.

“archive contains MVT vector tiles, but leafletRasterLayer is for displaying raster tiles”

Bu hata pmtiles.leafletRasterLayer işlevinden gelir; bu işlev raster PMTiles verilerini resim olarak çizer. Bunlar vektör karolar olduğu için onları reddeder. Hiçbir seçenek bunu değiştirmez ve burada raster kopya yoktur. Yukarıdaki seçeneklerden birini kullanın.

“download.openstreetmap.fr returned 403”

Burası bir karo sunucusu değil, bir veri dökümü ve çoğaltma yansısıdır. Ekim 2026'da aşırı indirmeler sonrasında adresleri engelledi ve işletmeciler erişimi duruma göre geri açacaklarını söyledi. Buradaki hiçbir şey buna ihtiyaç duymaz: bu arşiv Protomaps sürümlerinden gelir, yani .osm.pbf dosyasını kendiniz birleştirmezsiniz. OSM verisi çekiyorsanız dakikalık akış yerine belirli aralıklarla yayınlanan dökümleri alın.

Stiller

Aynı karolar, farklı renkler. Birini seçin, kopyalayın, değiştirin; sizindir.

StilGörünümDosya

Karolarda ne var

Sayfa yüklendiğinde arşivin kendi üstverisinden okunur. Bir stilin kullanması gereken katman adları bunlardır.

Kaynak katmanYakınlaştırmaAlanlar
yükleniyor…

Bu hizmet ne değildir

Sonradan hiçbir şeyin sizi şaşırtmaması için açık yanıtlar.

Bu ne kadar güncel?

Karolar, ayda bir kez yeniden derlenen Protomaps Basemap kopyasıdır.

Stil JSON'u

open raw