Files
hnh-map/frontend-nuxt/lib/LeafletCustomTypes.ts
Nikolay Tatarinov 051719381a Enhance frontend UI and functionality
- Added page transition effects in app.vue for smoother navigation.
- Updated nuxt.config.ts to include custom font styles and page transitions.
- Improved loading indicators in MapPageWrapper.vue and login.vue for better user experience.
- Enhanced MapView.vue with a collapsible control panel and improved styling.
- Introduced new icons for various components to enhance visual consistency.
- Updated Tailwind CSS configuration to extend font families and improve theme management.
- Refined layout styles in default.vue and admin pages for better responsiveness and aesthetics.
- Implemented error handling and loading states across various forms for improved user feedback.
2026-02-25 00:16:22 +03:00

92 lines
3.6 KiB
TypeScript

import L, { Bounds, LatLng, Point } from 'leaflet'
export const TileSize = 100
export const HnHMaxZoom = 6
export const HnHMinZoom = 1
export const HnHDefaultZoom = 6
/** When scaleFactor exceeds this, render one label per tile instead of a full grid (avoids 100k+ DOM nodes at zoom 1). */
const GRID_COORD_SCALE_FACTOR_THRESHOLD = 8
export const GridCoordLayer = L.GridLayer.extend({
options: {
visible: true,
},
createTile(coords: { x: number; y: number; z: number }) {
if (!this.options.visible) {
const element = document.createElement('div')
element.style.width = TileSize + 'px'
element.style.height = TileSize + 'px'
element.classList.add('map-tile')
return element
}
const element = document.createElement('div')
element.style.width = TileSize + 'px'
element.style.height = TileSize + 'px'
element.style.position = 'relative'
element.classList.add('map-tile')
const scaleFactor = Math.pow(2, HnHMaxZoom - coords.z)
const topLeft = { x: coords.x * scaleFactor, y: coords.y * scaleFactor }
const bottomRight = { x: topLeft.x + scaleFactor - 1, y: topLeft.y + scaleFactor - 1 }
const swPoint = { x: topLeft.x * TileSize, y: topLeft.y * TileSize }
const tileWidthPx = scaleFactor * TileSize
const tileHeightPx = scaleFactor * TileSize
if (scaleFactor > GRID_COORD_SCALE_FACTOR_THRESHOLD) {
// Low zoom: one label per tile to avoid hundreds of thousands of DOM nodes (Reset view freeze fix)
const textElement = document.createElement('div')
textElement.classList.add('map-tile-text')
textElement.textContent = `(${topLeft.x}, ${topLeft.y})`
textElement.style.position = 'absolute'
textElement.style.left = '2px'
textElement.style.top = '2px'
textElement.style.fontSize = Math.max(8, 12 - Math.log2(scaleFactor) * 2) + 'px'
element.appendChild(textElement)
return element
}
for (let gx = topLeft.x; gx <= bottomRight.x; gx++) {
for (let gy = topLeft.y; gy <= bottomRight.y; gy++) {
const leftPx = tileWidthPx > 0 ? ((gx * TileSize - swPoint.x) / tileWidthPx) * TileSize : 0
const topPx = tileHeightPx > 0 ? ((gy * TileSize - swPoint.y) / tileHeightPx) * TileSize : 0
const textElement = document.createElement('div')
textElement.classList.add('map-tile-text')
textElement.textContent = `(${gx}, ${gy})`
textElement.style.position = 'absolute'
textElement.style.left = leftPx + 2 + 'px'
textElement.style.top = topPx + 2 + 'px'
if (scaleFactor > 1) {
textElement.style.fontSize = Math.max(8, 12 - Math.log2(scaleFactor) * 2) + 'px'
}
element.appendChild(textElement)
}
}
return element
},
}) as unknown as new (options?: L.GridLayerOptions) => L.GridLayer
export const ImageIcon = L.Icon.extend({
options: {
iconSize: [32, 32],
iconAnchor: [16, 16],
},
}) as unknown as new (options?: L.IconOptions) => L.Icon
const latNormalization = (90.0 * TileSize) / 2500000.0
const lngNormalization = (180.0 * TileSize) / 2500000.0
const HnHProjection = {
project(latlng: LatLng) {
return new Point(latlng.lat / latNormalization, latlng.lng / lngNormalization)
},
unproject(point: Point) {
return new LatLng(point.x * latNormalization, point.y * lngNormalization)
},
bounds: (() => new Bounds([-latNormalization, -lngNormalization], [latNormalization, lngNormalization]))(),
}
export const HnHCRS = L.extend({}, L.CRS.Simple, {
projection: HnHProjection,
}) as L.CRS