62 lines
1.7 KiB
TypeScript
62 lines
1.7 KiB
TypeScript
export interface TileItem {
|
|
key: string
|
|
url: string
|
|
x: number
|
|
y: number
|
|
leftPx: number
|
|
topPx: number
|
|
sizePx: number
|
|
isCenter: boolean
|
|
}
|
|
|
|
const TILE_OVERLAP_PX = 2
|
|
|
|
export interface TileGridOptions {
|
|
urlTemplate: string
|
|
zoom: number
|
|
centerTileX: number
|
|
centerTileY: number
|
|
viewportWidth: number
|
|
viewportHeight: number
|
|
tileSize: number
|
|
overdraw: number
|
|
}
|
|
|
|
export function buildTileUrl(template: string, z: number, x: number, y: number): string {
|
|
return template
|
|
.replace('{z}', String(z))
|
|
.replace('{x}', String(x))
|
|
.replace('{y}', String(y))
|
|
}
|
|
|
|
export function createTileGrid(options: TileGridOptions): TileItem[] {
|
|
const tiles: TileItem[] = []
|
|
const halfWidth = options.viewportWidth / 2
|
|
const halfHeight = options.viewportHeight / 2
|
|
const horizontalRange = Math.ceil(halfWidth / options.tileSize) + options.overdraw
|
|
const verticalRange = Math.ceil(halfHeight / options.tileSize) + options.overdraw
|
|
|
|
for (let dy = -verticalRange; dy <= verticalRange; dy += 1) {
|
|
for (let dx = -horizontalRange; dx <= horizontalRange; dx += 1) {
|
|
const x = options.centerTileX + dx
|
|
const y = options.centerTileY + dy
|
|
|
|
const rawLeft = halfWidth + (dx - 0.5) * options.tileSize
|
|
const rawTop = halfHeight + (dy - 0.5) * options.tileSize
|
|
|
|
tiles.push({
|
|
key: `${options.zoom}-${x}-${y}`,
|
|
url: buildTileUrl(options.urlTemplate, options.zoom, x, y),
|
|
x,
|
|
y,
|
|
leftPx: Math.floor(rawLeft - TILE_OVERLAP_PX / 2),
|
|
topPx: Math.floor(rawTop - TILE_OVERLAP_PX / 2),
|
|
sizePx: Math.ceil(options.tileSize) + TILE_OVERLAP_PX,
|
|
isCenter: dx === 0 && dy === 0,
|
|
})
|
|
}
|
|
}
|
|
|
|
return tiles
|
|
}
|