Files
cmr-mini/miniprogram/utils/tile.ts

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
}