Update PMTiles docs & bump NDK version (#4278)
Co-authored-by: Bart Louwers <bart@emeel.net>
This commit is contained in:
@@ -769,6 +769,18 @@
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activity.FeatureOverviewActivity" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.sources.PMTilesActivity"
|
||||
android:description="@string/description_pmtiles"
|
||||
android:exported="true"
|
||||
android:label="@string/activity_pmtiles">
|
||||
<meta-data
|
||||
android:name="@string/category"
|
||||
android:value="@string/category_data" />
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activity.FeatureOverviewActivity" />
|
||||
</activity> <!-- Features -->
|
||||
<activity
|
||||
android:name=".activity.feature.QueryRenderedFeaturesPropertiesActivity"
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.maplibre.android.testapp.activity.sources
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.maplibre.android.camera.CameraPosition
|
||||
import org.maplibre.android.geometry.LatLng
|
||||
import org.maplibre.android.maps.MapView
|
||||
import org.maplibre.android.maps.Style
|
||||
import org.maplibre.android.style.layers.CircleLayer
|
||||
import org.maplibre.android.style.layers.PropertyFactory
|
||||
import org.maplibre.android.style.layers.RasterLayer
|
||||
import org.maplibre.android.style.sources.RasterSource
|
||||
import org.maplibre.android.style.sources.VectorSource
|
||||
import org.maplibre.android.testapp.R
|
||||
|
||||
class PMTilesActivity : AppCompatActivity() {
|
||||
private lateinit var mapView: MapView
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_pmtiles)
|
||||
mapView = findViewById(R.id.mapView)
|
||||
|
||||
mapView.getMapAsync { map ->
|
||||
// --8<-- [start:loadStyle]
|
||||
map.setStyle("https://demotiles.maplibre.org/pmtiles/raster/style-imagery.json") { style ->
|
||||
map.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(47.5, 12.0))
|
||||
.zoom(9.0)
|
||||
.build()
|
||||
// --8<-- [end:loadStyle]
|
||||
addPlaces(style)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addPlaces(style: Style) {
|
||||
// --8<-- [start:addSource]
|
||||
val overtureSource = VectorSource(
|
||||
"overture-places",
|
||||
"pmtiles://https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/2026-01-21/places.pmtiles"
|
||||
)
|
||||
style.addSource(overtureSource)
|
||||
val overtureLayer = CircleLayer("overture-layer", "overture-places")
|
||||
overtureLayer.setSourceLayer("place")
|
||||
overtureLayer.setProperties(
|
||||
PropertyFactory.circleColor(Color.parseColor("#f5c800")),
|
||||
PropertyFactory.circleRadius(4f),
|
||||
PropertyFactory.circleOpacity(0.6f)
|
||||
)
|
||||
style.addLayer(overtureLayer)
|
||||
// --8<-- [end:addSource]
|
||||
|
||||
val foursquareSource = VectorSource(
|
||||
"foursquare-places",
|
||||
"pmtiles://https://oliverwipfli.ch/data/foursquare-os-places-10M-2024-11-20.pmtiles"
|
||||
)
|
||||
style.addSource(foursquareSource)
|
||||
val foursquareLayer = CircleLayer("foursquare-layer", "foursquare-places")
|
||||
foursquareLayer.setSourceLayer("place")
|
||||
foursquareLayer.setProperties(
|
||||
PropertyFactory.circleColor(Color.parseColor("#2dd9fe")),
|
||||
PropertyFactory.circleRadius(4f),
|
||||
PropertyFactory.circleOpacity(0.6f)
|
||||
)
|
||||
style.addLayer(foursquareLayer)
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
private fun addLocalRasterSource(style: Style) {
|
||||
// --8<-- [start:loadFromFile]
|
||||
val path = getExternalFilesDir(null)?.absolutePath + "/watercolor.pmtiles"
|
||||
val source = RasterSource(
|
||||
"watercolor",
|
||||
"pmtiles://file://$path",
|
||||
256
|
||||
)
|
||||
style.addSource(source)
|
||||
style.addLayer(RasterLayer("watercolor", "watercolor"))
|
||||
// --8<-- [end:loadFromFile]
|
||||
}
|
||||
|
||||
override fun onStart() { super.onStart(); mapView.onStart() }
|
||||
override fun onResume() { super.onResume(); mapView.onResume() }
|
||||
override fun onPause() { super.onPause(); mapView.onPause() }
|
||||
override fun onStop() { super.onStop(); mapView.onStop() }
|
||||
override fun onLowMemory() { super.onLowMemory(); mapView.onLowMemory() }
|
||||
override fun onDestroy() { super.onDestroy(); mapView.onDestroy() }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activity.sources.PMTilesActivity">
|
||||
|
||||
<org.maplibre.android.maps.MapView
|
||||
android:id="@id/mapView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</RelativeLayout>
|
||||
@@ -85,6 +85,7 @@
|
||||
<string name="description_grid_source">Example Custom Geometry Source</string>
|
||||
<string name="description_no_style">Load a map without providing a style URI or JSON</string>
|
||||
<string name="description_vector_tile">Load MVT data</string>
|
||||
<string name="description_pmtiles">Load PMTiles data</string>
|
||||
<string name="description_local_glyph">Suzhou using Droid Sans for Chinese glyphs</string>
|
||||
<string name="description_hillshade">Example raster-dem source and hillshade layer</string>
|
||||
<string name="description_heatmaplayer">Use HeatmapLayer to visualise earthquakes</string>
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
<string name="activity_grid_source">Grid Source</string>
|
||||
<string name="activity_no_style">No Style URI/JSON</string>
|
||||
<string name="activity_vector_tile">Vector Tile source</string>
|
||||
<string name="activity_pmtiles">PMTiles</string>
|
||||
<string name="activity_local_glyph">Local CJK glyph generation</string>
|
||||
<string name="activity_hillshade">Hillshade</string>
|
||||
<string name="activity_heatmaplayer">Heatmap layer</string>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
object Versions {
|
||||
const val ndkVersion = "28.1.13356709"
|
||||
const val ndkVersion = "28.2.13676358"
|
||||
const val cmakeVersion = "3.24.0+"
|
||||
}
|
||||
|
||||
@@ -1,17 +1,44 @@
|
||||
# PMTiles
|
||||
|
||||
Starting MapLibre Android 11.7.0, using [PMTiles](https://docs.protomaps.com/pmtiles/) as a data source is supported. You can prefix your vector tile source with `pmtiles://` to load a PMTiles file. The rest of the URL continue with be `https://` to load a remote PMTiles file, `asset://` to load an asset or `file://` to load a local PMTiles file.
|
||||
{{ activity_source_note("PMTilesActivity.kt") }}
|
||||
|
||||
> Note: PMTiles sources do not currently support offline pack downloads.
|
||||
Starting MapLibre Android 11.7.0, [PMTiles](https://docs.protomaps.com/pmtiles/) archives are supported as tile sources. Prefix any tile source URL with `pmtiles://` to read from a PMTiles archive:
|
||||
|
||||
Oliver Wipfli has made a style available that combines a [Protomaps]() basemap togehter with Foursquare's POI dataset. It is available in the [wipfli/foursquare-os-places-pmtiles](https://github.com/wipfli/foursquare-os-places-pmtiles) repository on GitHub. The style to use is
|
||||
- `pmtiles://https://` — stream tiles from a remote file
|
||||
- `pmtiles://file://` — read a file from device storage (use `getExternalFilesDir` or `filesDir` for the path)
|
||||
|
||||
```
|
||||
https://raw.githubusercontent.com/wipfli/foursquare-os-places-pmtiles/refs/heads/main/style.json
|
||||
The `pmtiles://` prefix works with any [tile source type](https://maplibre.org/maplibre-style-spec/sources/) (e.g. `vector`, `raster`, `raster-dem`, etc.), from a style JSON or dynamically.
|
||||
|
||||
Unlike MapLibre GL JS, which resolves relative URLs against the style's base URL, MapLibre Native requires the URL inside `pmtiles://` to be fully specified (e.g. `pmtiles://https://example.com/tiles.pmtiles`, not `pmtiles://tiles.pmtiles`).
|
||||
|
||||
> Note: PMTiles sources do not support offline pack downloads or caching.
|
||||
|
||||
## Loading a style that uses PMTiles sources
|
||||
|
||||
Load a style JSON that references `pmtiles://` sources. The example below loads a satellite imagery basemap of the Central Alps and sets the initial camera position:
|
||||
|
||||
```kotlin
|
||||
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/sources/PMTilesActivity.kt:loadStyle"
|
||||
```
|
||||
|
||||
The neat thing about this style is that it only uses PMTiles vector sources. PMTiles can be hosted with a relatively simple file server (or file hosting service) instead of a more complex specialized tile server.
|
||||
## Adding a PMTiles source directly
|
||||
|
||||
<figure markdown="span">
|
||||
 }}){ width="300" }
|
||||
</figure>
|
||||
Add `vector` sources from PMTiles archives to an already-loaded style. The example overlays two places datasets — [Overture Maps](https://overturemaps.org/) (yellow) and [Foursquare OS Places](https://opensource.foursquare.com/os-places/) (blue) — both using `CircleLayer`. The `setSourceLayer` call names the layer within the archive to render:
|
||||
|
||||
```kotlin
|
||||
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/sources/PMTilesActivity.kt:addSource"
|
||||
```
|
||||
|
||||
The same pattern works for `raster` archives using `RasterSource` and `RasterLayer`.
|
||||
|
||||
> Note: `raster-dem` sources added programmatically cannot specify `encoding` via the current Android API. Define `raster-dem` sources with terrarium encoding in the style JSON instead, where the `encoding` field is fully supported.
|
||||
|
||||
## Loading a local PMTiles file
|
||||
|
||||
For files on device storage, use `file://` with an absolute path. The example below uses `getExternalFilesDir(null)` to locate a file downloaded to the app's external files directory:
|
||||
|
||||
```kotlin
|
||||
--8<-- "MapLibreAndroidTestApp/src/main/java/org/maplibre/android/testapp/activity/sources/PMTilesActivity.kt:loadFromFile"
|
||||
```
|
||||
|
||||
> Note: `pmtiles://asset://` (files in `src/main/assets/`) is not currently supported. `AssetManagerFileSource` does not implement byte-range reads, which PMTiles requires to read its header and metadata. Use `file://` from device storage instead. See the [open issue](https://github.com/maplibre/maplibre-native/issues/4360) for status.
|
||||
|
||||
@@ -65,6 +65,7 @@ Enabling the action journal.
|
||||
```swift
|
||||
let options = MLNMapOptions()
|
||||
options.actionJournalOptions.enabled = true
|
||||
options.actionJournalOptions.renderingStatsReportInterval = 10
|
||||
options.styleURL = AMERICANA_STYLE
|
||||
mapView = MLNMapView(frame: view.bounds, options: options)
|
||||
```
|
||||
|
||||
@@ -89,10 +89,15 @@ class CustomStyleLayer: MLNCustomStyleLayer {
|
||||
}
|
||||
"""
|
||||
|
||||
var error: NSError?
|
||||
let device = resource.device
|
||||
let library = try? device?.makeLibrary(source: shaderSource, options: nil)
|
||||
assert(library != nil, "Error compiling shaders: \(String(describing: error))")
|
||||
var library: MTLLibrary? = nil
|
||||
var shaderError: Error? = nil
|
||||
do {
|
||||
library = try device?.makeLibrary(source: shaderSource, options: nil)
|
||||
} catch {
|
||||
shaderError = error
|
||||
}
|
||||
assert(library != nil, "Error compiling shaders: \(String(describing: shaderError))")
|
||||
let vertexFunction = library?.makeFunction(name: "vertexShader")
|
||||
let fragmentFunction = library?.makeFunction(name: "fragmentShader")
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ The following styles are used in the examples:
|
||||
<!-- include-example(ExampleStyles) -->
|
||||
|
||||
```swift
|
||||
let AMERICANA_STYLE = URL(string:
|
||||
"https://americanamap.org/style.json")
|
||||
|
||||
let DEMOTILES_STYLE = URL(string: "https://demotiles.maplibre.org/style.json")
|
||||
let AMERICANA_STYLE = URL(string: "https://americanamap.org/style.json")
|
||||
let OPENFREEMAP_LIBERTY_STYLE = URL(string: "https://tiles.openfreemap.org/styles/liberty")
|
||||
let OPENFREEMAP_BRIGHT_STYLE = URL(string: "https://tiles.openfreemap.org/styles/bright")
|
||||
let VERSATILES_COLORFUL_STYLE = URL(string: "https://tiles.versatiles.org/assets/styles/colorful.json")
|
||||
```
|
||||
|
||||
@@ -64,7 +64,7 @@ class PrivacyExampleCoordinator: NSObject, MLNMapViewDelegate {
|
||||
super.init()
|
||||
}
|
||||
|
||||
@MainActor func mapView(_: MLNMapView, didChangeLocationManagerAuthorization manager: MLNLocationManager) {
|
||||
func mapView(_: MLNMapView, didChangeLocationManagerAuthorization manager: MLNLocationManager) {
|
||||
guard let accuracySetting = manager.accuracyAuthorization else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -13,9 +13,7 @@ Observe frame rendering statistics with ``MLNMapViewDelegate/mapViewDidFinishRen
|
||||
<!-- include-example(ObserverExampleRenderingStats) -->
|
||||
|
||||
```swift
|
||||
func mapViewDidFinishRenderingFrame(_: MLNMapView, fullyRendered: Bool, renderingStats: MLNRenderingStats) {
|
||||
|
||||
}
|
||||
func mapViewDidFinishRenderingFrame(_: MLNMapView, fullyRendered _: Bool, renderingStats _: MLNRenderingStats) {}
|
||||
```
|
||||
|
||||
See also: ``MLNMapViewDelegate/mapViewDidFinishRenderingFrame:fullyRendered:`` and ``MLNMapViewDelegate/mapViewDidFinishRenderingFrame:fullyRendered:frameEncodingTime:frameRenderingTime:``
|
||||
|
||||
@@ -2,16 +2,133 @@
|
||||
|
||||
Working with PMTiles
|
||||
|
||||
Starting MapLibre iOS 6.10.0, using [PMTiles](https://docs.protomaps.com/pmtiles/) as a data source is supported. You can prefix your vector tile source with `pmtiles://` to load a PMTiles file. The rest of the URL continue with be `https://` to load a remote PMTiles file, `asset://` to load an asset or `file://` to load a local PMTiles file.
|
||||
Starting MapLibre iOS 6.10.0, [PMTiles](https://docs.protomaps.com/pmtiles/) archives are supported as tile sources. Prefix any tile source URL with `pmtiles://` to read from a PMTiles archive:
|
||||
|
||||
> Note: PMTiles sources do not currently support offline pack downloads.
|
||||
- `pmtiles://https://` — stream tiles from a remote file
|
||||
- `pmtiles://file://` — read a file from the device filesystem, including the app bundle
|
||||
|
||||
Oliver Wipfli has made a style available that combines a [Protomaps]() basemap togehter with Foursquare's POI dataset. It is available in the [wipfli/foursquare-os-places-pmtiles](https://github.com/wipfli/foursquare-os-places-pmtiles) repository on GitHub. The style to use is
|
||||
The `pmtiles://` prefix works with any [tile source type](https://maplibre.org/maplibre-style-spec/sources/) (e.g. `vector`, `raster`, `raster-dem`, etc.), from a style JSON or dynamically.
|
||||
|
||||
```
|
||||
https://raw.githubusercontent.com/wipfli/foursquare-os-places-pmtiles/refs/heads/main/style.json
|
||||
> Note: PMTiles sources do not support offline pack downloads or caching.
|
||||
|
||||
## Loading a style that uses PMTiles sources
|
||||
|
||||
Load a style JSON that references `pmtiles://` sources. The example below loads a satellite imagery basemap of the Central Alps and sets the initial camera position:
|
||||
|
||||
<!-- include-example(PMTilesStyleURL) -->
|
||||
|
||||
```swift
|
||||
class PMTilesStyleURL: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
let mapView = MLNMapView(
|
||||
frame: view.bounds,
|
||||
styleURL: URL(string: "https://demotiles.maplibre.org/pmtiles/raster/style-imagery.json")!
|
||||
)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.setCenter(CLLocationCoordinate2D(latitude: 47.5, longitude: 12.0), zoomLevel: 9, animated: false)
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The neat thing about this style is that it only uses PMTiles vector sources. PMTiles can be hosted with a relatively simple file server (or file hosting service) instead of a more complex specialized tile server.
|
||||
## Adding a PMTiles source directly
|
||||
|
||||

|
||||
Add `vector` sources from PMTiles archives to an already-loaded style. The example overlays two places datasets — [Overture Maps](https://overturemaps.org/) (yellow) and [Foursquare OS Places](https://opensource.foursquare.com/os-places/) (blue) — both using `MLNCircleStyleLayer`. The `sourceLayerIdentifier` names the layer within the archive to render:
|
||||
|
||||
<!-- include-example(PMTilesAddSource) -->
|
||||
|
||||
```swift
|
||||
class PMTilesAddSource: UIViewController, MLNMapViewDelegate {
|
||||
var mapView: MLNMapView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
mapView = MLNMapView(frame: view.bounds)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.delegate = self
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
|
||||
func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
|
||||
let overtureURL = URL(string: "pmtiles://https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/2026-01-21/places.pmtiles")!
|
||||
let overtureSource = MLNVectorTileSource(identifier: "overture-places", configurationURL: overtureURL)
|
||||
style.addSource(overtureSource)
|
||||
let overtureLayer = MLNCircleStyleLayer(identifier: "overture-layer", source: overtureSource)
|
||||
overtureLayer.sourceLayerIdentifier = "place"
|
||||
overtureLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.96, green: 0.78, blue: 0.0, alpha: 1))
|
||||
overtureLayer.circleRadius = NSExpression(forConstantValue: 4)
|
||||
overtureLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
|
||||
style.addLayer(overtureLayer)
|
||||
|
||||
let foursquareURL = URL(string: "pmtiles://https://oliverwipfli.ch/data/foursquare-os-places-10M-2024-11-20.pmtiles")!
|
||||
let foursquareSource = MLNVectorTileSource(identifier: "foursquare-places", configurationURL: foursquareURL)
|
||||
style.addSource(foursquareSource)
|
||||
let foursquareLayer = MLNCircleStyleLayer(identifier: "foursquare-layer", source: foursquareSource)
|
||||
foursquareLayer.sourceLayerIdentifier = "place"
|
||||
foursquareLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.18, green: 0.85, blue: 1.0, alpha: 1))
|
||||
foursquareLayer.circleRadius = NSExpression(forConstantValue: 4)
|
||||
foursquareLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
|
||||
style.addLayer(foursquareLayer)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The same pattern works for `raster` archives using `MLNRasterTileSource` and `MLNRasterStyleLayer`:
|
||||
|
||||
<!-- include-example(PMTilesRasterSource) -->
|
||||
|
||||
```swift
|
||||
class PMTilesRasterSource: UIViewController, MLNMapViewDelegate {
|
||||
var mapView: MLNMapView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
mapView = MLNMapView(frame: view.bounds)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.delegate = self
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
|
||||
func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
|
||||
let url = URL(string: "pmtiles://https://demotiles.maplibre.org/pmtiles/raster/imagery.pmtiles")!
|
||||
let source = MLNRasterTileSource(identifier: "imagery", configurationURL: url, tileSize: 256)
|
||||
style.addSource(source)
|
||||
let layer = MLNRasterStyleLayer(identifier: "imagery", source: source)
|
||||
style.addLayer(layer)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> Note: `raster-dem` sources added programmatically cannot specify `encoding` via the current iOS API. Define `raster-dem` sources with terrarium encoding in the style JSON instead, where the `encoding` field is fully supported.
|
||||
|
||||
## Loading a local PMTiles file
|
||||
|
||||
Bundle a `.pmtiles` file in your app target and reference it using its bundle URL. iOS app bundle files are accessible via `file://`, so no special handling is needed:
|
||||
|
||||
<!-- include-example(PMTilesLocalFile) -->
|
||||
|
||||
```swift
|
||||
class PMTilesLocalFile: UIViewController, MLNMapViewDelegate {
|
||||
var mapView: MLNMapView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
mapView = MLNMapView(frame: view.bounds)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.delegate = self
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
|
||||
func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
|
||||
guard let fileURL = Bundle.main.url(forResource: "world", withExtension: "pmtiles") else { return }
|
||||
let url = URL(string: "pmtiles://\(fileURL.absoluteString)")!
|
||||
let source = MLNVectorTileSource(identifier: "world", configurationURL: url)
|
||||
style.addSource(source)
|
||||
let layer = MLNFillStyleLayer(identifier: "countries", source: source)
|
||||
layer.sourceLayerIdentifier = "countries"
|
||||
layer.fillColor = NSExpression(forConstantValue: UIColor(red: 0.67, green: 0.83, blue: 0.87, alpha: 1))
|
||||
style.addLayer(layer)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
125
platform/ios/app-swift/Sources/PMTilesExample.swift
Normal file
125
platform/ios/app-swift/Sources/PMTilesExample.swift
Normal file
@@ -0,0 +1,125 @@
|
||||
import MapLibre
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
// #-example-code(PMTilesStyleURL)
|
||||
class PMTilesStyleURL: UIViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
let mapView = MLNMapView(
|
||||
frame: view.bounds,
|
||||
styleURL: URL(string: "https://demotiles.maplibre.org/pmtiles/raster/style-imagery.json")!
|
||||
)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.setCenter(CLLocationCoordinate2D(latitude: 47.5, longitude: 12.0), zoomLevel: 9, animated: false)
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
}
|
||||
|
||||
// #-end-example-code
|
||||
|
||||
// #-example-code(PMTilesAddSource)
|
||||
class PMTilesAddSource: UIViewController, MLNMapViewDelegate {
|
||||
var mapView: MLNMapView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
mapView = MLNMapView(frame: view.bounds)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.delegate = self
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
|
||||
func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
|
||||
let overtureURL = URL(string: "pmtiles://https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/2026-01-21/places.pmtiles")!
|
||||
let overtureSource = MLNVectorTileSource(identifier: "overture-places", configurationURL: overtureURL)
|
||||
style.addSource(overtureSource)
|
||||
let overtureLayer = MLNCircleStyleLayer(identifier: "overture-layer", source: overtureSource)
|
||||
overtureLayer.sourceLayerIdentifier = "place"
|
||||
overtureLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.96, green: 0.78, blue: 0.0, alpha: 1))
|
||||
overtureLayer.circleRadius = NSExpression(forConstantValue: 4)
|
||||
overtureLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
|
||||
style.addLayer(overtureLayer)
|
||||
|
||||
let foursquareURL = URL(string: "pmtiles://https://oliverwipfli.ch/data/foursquare-os-places-10M-2024-11-20.pmtiles")!
|
||||
let foursquareSource = MLNVectorTileSource(identifier: "foursquare-places", configurationURL: foursquareURL)
|
||||
style.addSource(foursquareSource)
|
||||
let foursquareLayer = MLNCircleStyleLayer(identifier: "foursquare-layer", source: foursquareSource)
|
||||
foursquareLayer.sourceLayerIdentifier = "place"
|
||||
foursquareLayer.circleColor = NSExpression(forConstantValue: UIColor(red: 0.18, green: 0.85, blue: 1.0, alpha: 1))
|
||||
foursquareLayer.circleRadius = NSExpression(forConstantValue: 4)
|
||||
foursquareLayer.circleOpacity = NSExpression(forConstantValue: 0.6)
|
||||
style.addLayer(foursquareLayer)
|
||||
}
|
||||
}
|
||||
|
||||
// #-end-example-code
|
||||
|
||||
// #-example-code(PMTilesRasterSource)
|
||||
class PMTilesRasterSource: UIViewController, MLNMapViewDelegate {
|
||||
var mapView: MLNMapView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
mapView = MLNMapView(frame: view.bounds)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.delegate = self
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
|
||||
func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
|
||||
let url = URL(string: "pmtiles://https://demotiles.maplibre.org/pmtiles/raster/imagery.pmtiles")!
|
||||
let source = MLNRasterTileSource(identifier: "imagery", configurationURL: url, tileSize: 256)
|
||||
style.addSource(source)
|
||||
let layer = MLNRasterStyleLayer(identifier: "imagery", source: source)
|
||||
style.addLayer(layer)
|
||||
}
|
||||
}
|
||||
|
||||
// #-end-example-code
|
||||
|
||||
// #-example-code(PMTilesLocalFile)
|
||||
class PMTilesLocalFile: UIViewController, MLNMapViewDelegate {
|
||||
var mapView: MLNMapView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
mapView = MLNMapView(frame: view.bounds)
|
||||
mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
mapView.delegate = self
|
||||
view.addSubview(mapView)
|
||||
}
|
||||
|
||||
func mapView(_: MLNMapView, didFinishLoading style: MLNStyle) {
|
||||
guard let fileURL = Bundle.main.url(forResource: "world", withExtension: "pmtiles") else { return }
|
||||
let url = URL(string: "pmtiles://\(fileURL.absoluteString)")!
|
||||
let source = MLNVectorTileSource(identifier: "world", configurationURL: url)
|
||||
style.addSource(source)
|
||||
let layer = MLNFillStyleLayer(identifier: "countries", source: source)
|
||||
layer.sourceLayerIdentifier = "countries"
|
||||
layer.fillColor = NSExpression(forConstantValue: UIColor(red: 0.67, green: 0.83, blue: 0.87, alpha: 1))
|
||||
style.addLayer(layer)
|
||||
}
|
||||
}
|
||||
|
||||
// #-end-example-code
|
||||
|
||||
struct PMTilesStyleURLRepresentable: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context _: Context) -> PMTilesStyleURL { PMTilesStyleURL() }
|
||||
func updateUIViewController(_: PMTilesStyleURL, context _: Context) {}
|
||||
}
|
||||
|
||||
struct PMTilesAddSourceRepresentable: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context _: Context) -> PMTilesAddSource { PMTilesAddSource() }
|
||||
func updateUIViewController(_: PMTilesAddSource, context _: Context) {}
|
||||
}
|
||||
|
||||
struct PMTilesRasterSourceRepresentable: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context _: Context) -> PMTilesRasterSource { PMTilesRasterSource() }
|
||||
func updateUIViewController(_: PMTilesRasterSource, context _: Context) {}
|
||||
}
|
||||
|
||||
struct PMTilesLocalFileRepresentable: UIViewControllerRepresentable {
|
||||
func makeUIViewController(context _: Context) -> PMTilesLocalFile { PMTilesLocalFile() }
|
||||
func updateUIViewController(_: PMTilesLocalFile, context _: Context) {}
|
||||
}
|
||||
Reference in New Issue
Block a user