forked from MapComplete/MapComplete
UX: center summary tiles, small style tweaks
This commit is contained in:
parent
020a1f8c3b
commit
38191309ca
4 changed files with 32 additions and 21 deletions
|
@ -29,8 +29,8 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"labelCss": "background: #ffffffbb",
|
||||
"labelCssClasses": "w-12 text-lg rounded-xl p-1 px-2"
|
||||
"labelCss": "background: #ffffffcc; min-width: 2rem",
|
||||
"labelCssClasses": "text-lg rounded p-1 px-2 border-2 border-gray font-bold"
|
||||
}
|
||||
],
|
||||
"tagRenderings": [
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Feature, Point } from "geojson"
|
|||
import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource"
|
||||
import { GeoOperations } from "../../GeoOperations"
|
||||
import { Tiles } from "../../../Models/TileRange"
|
||||
import { Lists } from "../../../Utils/Lists"
|
||||
|
||||
export interface ClusteringOptions {
|
||||
/**
|
||||
|
@ -86,11 +87,10 @@ export class ClusteringFeatureSource<T extends Feature<Point> = Feature<Point>>
|
|||
features: Feature<Point>[],
|
||||
tileId: number
|
||||
): Feature<Point, SummaryProperties> {
|
||||
let lon: number
|
||||
let lat: number
|
||||
const [z, x, y] = Tiles.tile_from_index(tileId)
|
||||
let coordinates: [number, number]
|
||||
if (this.showSummaryAt === "tilecenter") {
|
||||
;[lon, lat] = Tiles.centerPointOf(z, x, y)
|
||||
const [z, x, y] = Tiles.tile_from_index(tileId)
|
||||
coordinates = Tiles.centerPointOf(z, x, y)
|
||||
} else {
|
||||
let lonSum = 0
|
||||
let latSum = 0
|
||||
|
@ -99,14 +99,15 @@ export class ClusteringFeatureSource<T extends Feature<Point> = Feature<Point>>
|
|||
lonSum += lon
|
||||
latSum += lat
|
||||
}
|
||||
lon = lonSum / features.length
|
||||
lat = latSum / features.length
|
||||
const lon = lonSum / features.length
|
||||
const lat = latSum / features.length
|
||||
coordinates = [lon, lat]
|
||||
}
|
||||
return {
|
||||
type: "Feature",
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates: [lon, lat],
|
||||
coordinates
|
||||
},
|
||||
properties: {
|
||||
id: "summary_" + this.id + "_" + tileId,
|
||||
|
@ -120,10 +121,10 @@ export class ClusteringFeatureSource<T extends Feature<Point> = Feature<Point>>
|
|||
/**
|
||||
* Groups multiple summaries together
|
||||
*/
|
||||
export class ClusterGrouping implements FeatureSource<Feature<Point, { total_metric: string }>> {
|
||||
private readonly _features: UIEventSource<Feature<Point, { total_metric: string }>[]> =
|
||||
export class ClusterGrouping implements FeatureSource<Feature<Point, { total_metric: string, id: string }>> {
|
||||
private readonly _features: UIEventSource<Feature<Point, { total_metric: string, id: string }>[]> =
|
||||
new UIEventSource([])
|
||||
public readonly features: Store<Feature<Point, { total_metric: string }>[]> = this._features
|
||||
public readonly features: Store<Feature<Point, { total_metric: string, id: string }>[]> = this._features
|
||||
|
||||
public static readonly singleton = new ClusterGrouping()
|
||||
|
||||
|
@ -140,27 +141,34 @@ export class ClusterGrouping implements FeatureSource<Feature<Point, { total_met
|
|||
private allSource: Store<Feature<Point, { total: number; tile_id: number }>[]>[] = []
|
||||
|
||||
private update() {
|
||||
const countPerTile = new Map<number, number>()
|
||||
const countPerTile = new Map<number, { lon: number, lat: number, count: number }[]>()
|
||||
for (const source of this.allSource) {
|
||||
for (const f of source.data) {
|
||||
const id = f.properties.tile_id
|
||||
const count = f.properties.total + (countPerTile.get(id) ?? 0)
|
||||
countPerTile.set(id, count)
|
||||
if (!countPerTile.has(id)) {
|
||||
countPerTile.set(id, [])
|
||||
}
|
||||
const ls = countPerTile.get(id)
|
||||
ls.push({ lon: f.geometry.coordinates[0], lat: f.geometry.coordinates[1], count: f.properties.total })
|
||||
}
|
||||
}
|
||||
const features: Feature<Point, { total_metric: string; id: string }>[] = []
|
||||
const now = new Date().getTime() + ""
|
||||
for (const tileId of countPerTile.keys()) {
|
||||
const coordinates = Tiles.centerPointOf(tileId)
|
||||
const data = countPerTile.get(tileId)
|
||||
const total = Lists.sum(data.map(d => d.count))
|
||||
const lon = Lists.sum(data.map(d => d.lon * d.count)) / total
|
||||
const lat = Lists.sum(data.map(d => d.lat * d.count)) / total
|
||||
|
||||
features.push({
|
||||
type: "Feature",
|
||||
properties: {
|
||||
total_metric: "" + countPerTile.get(tileId),
|
||||
total_metric: "" + total,
|
||||
id: "clustered_all_" + tileId + "_" + now, // We add the date to force a fresh ID every time, this makes sure values are updated
|
||||
},
|
||||
geometry: {
|
||||
type: "Point",
|
||||
coordinates,
|
||||
coordinates: [lon, lat]
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -169,6 +177,10 @@ export class ClusterGrouping implements FeatureSource<Feature<Point, { total_met
|
|||
}
|
||||
|
||||
public registerSource(features: Store<Feature<Point, SummaryProperties>[]>) {
|
||||
if (this.allSource.indexOf(features) >= 0) {
|
||||
console.error("This source has already been registered")
|
||||
return
|
||||
}
|
||||
this.allSource.push(features)
|
||||
features.addCallbackAndRun(() => {
|
||||
//this.isDirty.set(true)
|
||||
|
|
|
@ -407,8 +407,7 @@ export default class ShowDataLayer {
|
|||
state.mapProperties.zoom.map((z) => z + 2),
|
||||
options.layer.id,
|
||||
{
|
||||
cutoff: 7,
|
||||
showSummaryAt: "tilecenter",
|
||||
cutoff: 7
|
||||
}
|
||||
)
|
||||
new ShowDataLayer(mlmap, options)
|
||||
|
|
|
@ -346,7 +346,7 @@
|
|||
<InsetSpacer height={AndroidPolyfill.getInsetSizes().top} />
|
||||
</div>
|
||||
<!-- Top bar with tools -->
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center" style="z-index: 10">
|
||||
<MapControlButton
|
||||
cls="m-0.5 p-0.5 sm:p-1"
|
||||
arialabel={Translations.t.general.labels.menu}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue