| 66 | } |
| 67 | |
| 68 | export class PMTilesVectorSource extends VectorTileSource { |
| 69 | pmtiles_: PMTiles; |
| 70 | |
| 71 | tileLoadFunction = (tile: Tile, url: string) => { |
| 72 | const vtile = tile as VectorTile; |
| 73 | // the URL construction is done internally by OL, so we need to parse it |
| 74 | // back out here using a hacky regex |
| 75 | const re = new RegExp(/pmtiles:\/\/(\d+)\/(\d+)\/(\d+)/); |
| 76 | const result = url.match(re); |
| 77 | |
| 78 | if (!(result && result.length >= 4)) { |
| 79 | throw Error("Could not parse tile URL"); |
| 80 | } |
| 81 | const z = +result[1]; |
| 82 | const x = +result[2]; |
| 83 | const y = +result[3]; |
| 84 | |
| 85 | vtile.setLoader( |
| 86 | (extent: Extent, resolution: number, projection: Projection) => { |
| 87 | this.pmtiles_ |
| 88 | .getZxy(z, x, y) |
| 89 | .then((tile_result) => { |
| 90 | if (tile_result) { |
| 91 | const format = vtile.getFormat(); |
| 92 | vtile.setFeatures( |
| 93 | format.readFeatures(tile_result.data, { |
| 94 | extent: extent, |
| 95 | featureProjection: projection, |
| 96 | }), |
| 97 | ); |
| 98 | vtile.setState(TileState.LOADED); |
| 99 | } else { |
| 100 | vtile.setFeatures([]); |
| 101 | vtile.setState(TileState.EMPTY); |
| 102 | } |
| 103 | }) |
| 104 | .catch((err) => { |
| 105 | vtile.setFeatures([]); |
| 106 | vtile.setState(TileState.ERROR); |
| 107 | }); |
| 108 | }, |
| 109 | ); |
| 110 | }; |
| 111 | |
| 112 | constructor( |
| 113 | options: VectorTileSourceOptions<RenderFeature> & { url: string | Source }, |
| 114 | ) { |
| 115 | super({ |
| 116 | ...options, |
| 117 | ...{ |
| 118 | state: "loading", |
| 119 | url: "pmtiles://{z}/{x}/{y}", |
| 120 | format: options.format || new MVT(), |
| 121 | }, |
| 122 | }); |
| 123 | |
| 124 | this.pmtiles_ = new PMTiles(options.url); |
| 125 | this.pmtiles_.getHeader().then((h: Header) => { |
nothing calls this directly
no test coverage detected
searching dependent graphs…