forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			63 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			63 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { Store, Stores } from "../../UIEventSource"
 | |
| import { Tiles } from "../../../Models/TileRange"
 | |
| import { BBox } from "../../BBox"
 | |
| import { FeatureSource } from "../FeatureSource"
 | |
| import FeatureSourceMerger from "../Sources/FeatureSourceMerger"
 | |
| 
 | |
| /***
 | |
|  * A tiled source which dynamically loads the required tiles at a fixed zoom level.
 | |
|  * A single featureSource will be initiliased for every tile in view; which will alter be merged into this featureSource
 | |
|  */
 | |
| export default class DynamicTileSource extends FeatureSourceMerger {
 | |
|     constructor(
 | |
|         zoomlevel: number,
 | |
|         constructSource: (tileIndex) => FeatureSource,
 | |
|         mapProperties: {
 | |
|             bounds: Store<BBox>
 | |
|             zoom: Store<number>
 | |
|         },
 | |
|         options?: {
 | |
|             isActive?: Store<boolean>
 | |
|         }
 | |
|     ) {
 | |
|         super()
 | |
|         const loadedTiles = new Set<number>()
 | |
|         const neededTiles: Store<number[]> = Stores.ListStabilized(
 | |
|             mapProperties.bounds
 | |
|                 .mapD(
 | |
|                     (bounds) => {
 | |
|                         const tileRange = Tiles.TileRangeBetween(
 | |
|                             zoomlevel,
 | |
|                             bounds.getNorth(),
 | |
|                             bounds.getEast(),
 | |
|                             bounds.getSouth(),
 | |
|                             bounds.getWest()
 | |
|                         )
 | |
|                         if (tileRange.total > 10000) {
 | |
|                             console.error(
 | |
|                                 "Got a really big tilerange, bounds and location might be out of sync"
 | |
|                             )
 | |
|                             return undefined
 | |
|                         }
 | |
| 
 | |
|                         const needed = Tiles.MapRange(tileRange, (x, y) =>
 | |
|                             Tiles.tile_index(zoomlevel, x, y)
 | |
|                         ).filter((i) => !loadedTiles.has(i))
 | |
|                         if (needed.length === 0) {
 | |
|                             return undefined
 | |
|                         }
 | |
|                         return needed
 | |
|                     },
 | |
|                     [options?.isActive, mapProperties.zoom]
 | |
|                 )
 | |
|                 .stabilized(250)
 | |
|         )
 | |
| 
 | |
|         neededTiles.addCallbackAndRunD((neededIndexes) => {
 | |
|             for (const neededIndex of neededIndexes) {
 | |
|                 loadedTiles.add(neededIndex)
 | |
|                 super.addSource(constructSource(neededIndex))
 | |
|             }
 | |
|         })
 | |
|     }
 | |
| }
 |