import { Feature as GeojsonFeature, Geometry } from "geojson" import { Store, UIEventSource } from "../../UIEventSource" import { FeatureSourceForTile, UpdatableFeatureSource } from "../FeatureSource" import { MvtToGeojson } from "mvt-to-geojson" export default class MvtSource implements FeatureSourceForTile, UpdatableFeatureSource { public readonly features: Store[]> public readonly x: number public readonly y: number public readonly z: number private readonly _url: string private readonly _layerName: string private readonly _features: UIEventSource< GeojsonFeature< Geometry, { [name: string]: any } >[] > = new UIEventSource[]>([]) private currentlyRunning: Promise constructor( url: string, x: number, y: number, z: number, layerName?: string, isActive?: Store, ) { this._url = url this._layerName = layerName this.x = x this.y = y this.z = z this.updateAsync() this.features = this._features.map( (fs) => { if (fs === undefined || isActive?.data === false) { return [] } return fs }, [isActive], ) } async updateAsync() { if (!this.currentlyRunning) { this.currentlyRunning = this.download() } await this.currentlyRunning } private async download(): Promise { try { const result = await fetch(this._url) if (result.status !== 200) { console.error("Could not download tile " + this._url) return } const buffer = await result.arrayBuffer() const features = MvtToGeojson.fromBuffer(buffer, this.x, this.y, this.z) for (const feature of features) { const properties = feature.properties if(!properties["osm_type"]){ continue } let type: string = "node" switch (properties["osm_type"]) { case "N": type = "node" break case "W": type = "way" break case "R": type = "relation" break } properties["id"] = type + "/" + properties["osm_id"] delete properties["osm_id"] delete properties["osm_type"] } this._features.setData(features) } catch (e) { console.error("Could not download MVT " + this._url + " tile due to", e) } } }