who_need_help/assets/js/map_cluster_features.mjs

60 lines
2.0 KiB
JavaScript

const finiteCount = (value, fallback) => {
const count = Number(value)
return Number.isFinite(count) && count >= 0 ? count : fallback
}
export const clusterSizeClass = count => {
if (count >= 100_000) return "is-xxl"
if (count >= 10_000) return "is-xl"
if (count >= 1_000) return "is-lg"
return "is-md"
}
export const clusterCountLabel = (count, locale = "en") => {
const value = finiteCount(count, 0)
if (value < 1_000) return new Intl.NumberFormat(locale).format(value)
return new Intl.NumberFormat(locale, {
notation: "compact",
maximumFractionDigits: value < 10_000 ? 1 : 0
}).format(value)
}
export const clusterExpansionTarget = (currentZoom, requestedZoom, maximumZoom = 22) => {
const current = finiteCount(currentZoom, 0)
const requested = finiteCount(requestedZoom, current + 1)
const nearestIntegerZoom = Math.round(current)
const normalizedCurrent =
Math.abs(current - nearestIntegerZoom) < 0.001 ? nearestIntegerZoom : current
const nextIntegerZoom = Math.floor(normalizedCurrent) + 1
return Math.min(maximumZoom, Math.max(nextIntegerZoom, requested))
}
export const pointFeatureCollection = points => ({
type: "FeatureCollection",
features: points.map(point => ({
type: "Feature",
id: point.id,
properties: {
id: point.id,
item_type: point.type || "request",
title: point.title || "",
location: point.location || "",
exact: point.exact === true,
radius_meters: Number.isFinite(point.radius_meters) ? point.radius_meters : 0,
weight: finiteCount(point.count, 1),
urgent_weight: finiteCount(point.urgent_count, 0),
server_cluster_id: point.cluster_id || "",
parent_cluster_id: point.parent_cluster_id || "",
hierarchy_level: finiteCount(point.hierarchy_level, 0),
expansion_zoom: finiteCount(point.expansion_zoom, 22)
},
geometry: {
type: "Point",
coordinates: [Number(point.longitude), Number(point.latitude)]
}
}))
})