forked from MapComplete/MapComplete
Refactoring of AvailableBaseLayer
This commit is contained in:
parent
99512724e0
commit
583d1e137f
5 changed files with 89 additions and 78 deletions
|
@ -341,7 +341,7 @@ export class InitUiElements {
|
||||||
|
|
||||||
private static InitBaseMap() {
|
private static InitBaseMap() {
|
||||||
|
|
||||||
State.state.availableBackgroundLayers = new AvailableBaseLayers(State.state.locationControl).availableEditorLayers;
|
State.state.availableBackgroundLayers = AvailableBaseLayers.AvailableLayersAt(State.state.locationControl);
|
||||||
|
|
||||||
State.state.backgroundLayer = State.state.backgroundLayerId
|
State.state.backgroundLayer = State.state.backgroundLayerId
|
||||||
.map((selectedId: string) => {
|
.map((selectedId: string) => {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {UIEventSource} from "../UIEventSource";
|
||||||
import {GeoOperations} from "../GeoOperations";
|
import {GeoOperations} from "../GeoOperations";
|
||||||
import {Utils} from "../../Utils";
|
import {Utils} from "../../Utils";
|
||||||
import Loc from "../../Models/Loc";
|
import Loc from "../../Models/Loc";
|
||||||
import {isBoolean} from "util";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates which layers are available at the current location
|
* Calculates which layers are available at the current location
|
||||||
|
@ -31,42 +30,82 @@ export default class AvailableBaseLayers {
|
||||||
category: "osmbasedmap"
|
category: "osmbasedmap"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex());
|
public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex());
|
||||||
public availableEditorLayers: UIEventSource<BaseLayer[]>;
|
|
||||||
|
|
||||||
constructor(location: UIEventSource<Loc>) {
|
public static AvailableLayersAt(location: UIEventSource<Loc>): UIEventSource<BaseLayer[]> {
|
||||||
const self = this;
|
const source = location.map(
|
||||||
this.availableEditorLayers =
|
(currentLocation) => {
|
||||||
location.map(
|
|
||||||
(currentLocation) => {
|
|
||||||
|
|
||||||
if (currentLocation === undefined) {
|
if (currentLocation === undefined) {
|
||||||
return AvailableBaseLayers.layerOverview;
|
return AvailableBaseLayers.layerOverview;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentLayers = self.availableEditorLayers?.data;
|
const currentLayers = source?.data; // A bit unorthodox - I know
|
||||||
const newLayers = AvailableBaseLayers.AvailableLayersAt(currentLocation?.lon, currentLocation?.lat);
|
const newLayers = AvailableBaseLayers.CalculateAvailableLayersAt(currentLocation?.lon, currentLocation?.lat);
|
||||||
|
|
||||||
if (currentLayers === undefined) {
|
if (currentLayers === undefined) {
|
||||||
|
return newLayers;
|
||||||
|
}
|
||||||
|
if (newLayers.length !== currentLayers.length) {
|
||||||
|
return newLayers;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < newLayers.length; i++) {
|
||||||
|
if (newLayers[i].name !== currentLayers[i].name) {
|
||||||
return newLayers;
|
return newLayers;
|
||||||
}
|
}
|
||||||
if (newLayers.length !== currentLayers.length) {
|
}
|
||||||
return newLayers;
|
|
||||||
}
|
|
||||||
for (let i = 0; i < newLayers.length; i++) {
|
|
||||||
if (newLayers[i].name !== currentLayers[i].name) {
|
|
||||||
return newLayers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentLayers;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
return currentLayers;
|
||||||
|
});
|
||||||
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AvailableLayersAt(lon: number, lat: number): BaseLayer[] {
|
public static SelectBestLayerAccordingTo(location: UIEventSource<Loc>, preferedCategory: UIEventSource<string | string[]>): UIEventSource<BaseLayer> {
|
||||||
|
return AvailableBaseLayers.AvailableLayersAt(location).map(available => {
|
||||||
|
// First float all 'best layers' to the top
|
||||||
|
available.sort((a, b) => {
|
||||||
|
if (a.isBest && b.isBest) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!a.isBest) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (preferedCategory.data === undefined) {
|
||||||
|
return available[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
let prefered: string []
|
||||||
|
if (typeof preferedCategory.data === "string") {
|
||||||
|
prefered = [preferedCategory.data]
|
||||||
|
} else {
|
||||||
|
prefered = preferedCategory.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefered.reverse();
|
||||||
|
for (const category of prefered) {
|
||||||
|
//Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top
|
||||||
|
available.sort((a, b) => {
|
||||||
|
if (a.category === preferedCategory && b.category === preferedCategory) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (a.category !== preferedCategory) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return available[0]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CalculateAvailableLayersAt(lon: number, lat: number): BaseLayer[] {
|
||||||
const availableLayers = [AvailableBaseLayers.osmCarto]
|
const availableLayers = [AvailableBaseLayers.osmCarto]
|
||||||
const globalLayers = [];
|
const globalLayers = [];
|
||||||
for (const layerOverviewItem of AvailableBaseLayers.layerOverview) {
|
for (const layerOverviewItem of AvailableBaseLayers.layerOverview) {
|
||||||
|
@ -146,7 +185,7 @@ export default class AvailableBaseLayers {
|
||||||
layer: leafletLayer,
|
layer: leafletLayer,
|
||||||
feature: layer,
|
feature: layer,
|
||||||
isBest: props.best ?? false,
|
isBest: props.best ?? false,
|
||||||
category: props.category
|
category: props.category
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return layers;
|
return layers;
|
||||||
|
|
|
@ -52,7 +52,7 @@ export default class Minimap extends BaseUIElement {
|
||||||
return wrapper;
|
return wrapper;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private InitMap() {
|
private InitMap() {
|
||||||
if (this._constructedHtmlElement === undefined) {
|
if (this._constructedHtmlElement === undefined) {
|
||||||
// This element isn't initialized yet
|
// This element isn't initialized yet
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {Translation} from "../i18n/Translation";
|
||||||
import LocationInput from "../Input/LocationInput";
|
import LocationInput from "../Input/LocationInput";
|
||||||
import {InputElement} from "../Input/InputElement";
|
import {InputElement} from "../Input/InputElement";
|
||||||
import Loc from "../../Models/Loc";
|
import Loc from "../../Models/Loc";
|
||||||
|
import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The SimpleAddUI is a single panel, which can have multiple states:
|
* The SimpleAddUI is a single panel, which can have multiple states:
|
||||||
|
@ -115,14 +116,21 @@ export default class SimpleAddUI extends Toggle {
|
||||||
let location = State.state.LastClickLocation;
|
let location = State.state.LastClickLocation;
|
||||||
let preciseInput: InputElement<Loc> = undefined
|
let preciseInput: InputElement<Loc> = undefined
|
||||||
if (preset.preciseInput !== undefined) {
|
if (preset.preciseInput !== undefined) {
|
||||||
|
const locationSrc = new UIEventSource({
|
||||||
|
lat: location.data.lat,
|
||||||
|
lon: location.data.lon,
|
||||||
|
zoom: 19
|
||||||
|
});
|
||||||
|
|
||||||
|
let backgroundLayer = undefined;
|
||||||
|
if(preset.preciseInput.preferredBackground){
|
||||||
|
backgroundLayer= AvailableBaseLayers.SelectBestLayerAccordingTo(locationSrc, new UIEventSource<string | string[]>(preset.preciseInput.preferredBackground))
|
||||||
|
}
|
||||||
|
|
||||||
preciseInput = new LocationInput({
|
preciseInput = new LocationInput({
|
||||||
preferCategory: preset.preciseInput.preferredBackground ?? State.state.backgroundLayer,
|
mapBackground: backgroundLayer,
|
||||||
centerLocation:
|
centerLocation:locationSrc
|
||||||
new UIEventSource({
|
|
||||||
lat: location.data.lat,
|
|
||||||
lon: location.data.lon,
|
|
||||||
zoom: 19
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;")
|
preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,30 +2,27 @@ import {InputElement} from "./InputElement";
|
||||||
import Loc from "../../Models/Loc";
|
import Loc from "../../Models/Loc";
|
||||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||||
import Minimap from "../Base/Minimap";
|
import Minimap from "../Base/Minimap";
|
||||||
import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
|
|
||||||
import BaseLayer from "../../Models/BaseLayer";
|
import BaseLayer from "../../Models/BaseLayer";
|
||||||
import Combine from "../Base/Combine";
|
import Combine from "../Base/Combine";
|
||||||
import Svg from "../../Svg";
|
import Svg from "../../Svg";
|
||||||
|
import State from "../../State";
|
||||||
|
|
||||||
export default class LocationInput extends InputElement<Loc> {
|
export default class LocationInput extends InputElement<Loc> {
|
||||||
|
|
||||||
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
||||||
private _centerLocation: UIEventSource<Loc>;
|
private _centerLocation: UIEventSource<Loc>;
|
||||||
private readonly preferCategory;
|
private readonly mapBackground : UIEventSource<BaseLayer>;
|
||||||
|
|
||||||
constructor(options?: {
|
constructor(options?: {
|
||||||
|
mapBackground?: UIEventSource<BaseLayer>,
|
||||||
centerLocation?: UIEventSource<Loc>,
|
centerLocation?: UIEventSource<Loc>,
|
||||||
preferCategory?: string | UIEventSource<string>,
|
|
||||||
}) {
|
}) {
|
||||||
super();
|
super();
|
||||||
options = options ?? {}
|
options = options ?? {}
|
||||||
options.centerLocation = options.centerLocation ?? new UIEventSource<Loc>({lat: 0, lon: 0, zoom: 1})
|
options.centerLocation = options.centerLocation ?? new UIEventSource<Loc>({lat: 0, lon: 0, zoom: 1})
|
||||||
this._centerLocation = options.centerLocation;
|
this._centerLocation = options.centerLocation;
|
||||||
|
|
||||||
if(typeof options.preferCategory === "string"){
|
this.mapBackground = options.mapBackground ?? State.state.backgroundLayer
|
||||||
options.preferCategory = new UIEventSource<string>(options.preferCategory);
|
|
||||||
}
|
|
||||||
this.preferCategory = options.preferCategory ?? new UIEventSource<string>(undefined)
|
|
||||||
this.SetClass("block h-full")
|
this.SetClass("block h-full")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,43 +35,10 @@ export default class LocationInput extends InputElement<Loc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected InnerConstructElement(): HTMLElement {
|
protected InnerConstructElement(): HTMLElement {
|
||||||
const layer: UIEventSource<BaseLayer> = new AvailableBaseLayers(this._centerLocation).availableEditorLayers.map(allLayers => {
|
|
||||||
// First float all 'best layers' to the top
|
|
||||||
allLayers.sort((a, b) => {
|
|
||||||
if (a.isBest && b.isBest) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!a.isBest) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (this.preferCategory) {
|
|
||||||
const self = this;
|
|
||||||
//Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top
|
|
||||||
allLayers.sort((a, b) => {
|
|
||||||
const preferred = self.preferCategory.data
|
|
||||||
if (a.category === preferred && b.category === preferred) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (a.category !== preferred) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return allLayers[0]
|
|
||||||
}, [this.preferCategory]
|
|
||||||
)
|
|
||||||
layer.addCallbackAndRunD(layer => console.log(layer))
|
|
||||||
const map = new Minimap(
|
const map = new Minimap(
|
||||||
{
|
{
|
||||||
location: this._centerLocation,
|
location: this._centerLocation,
|
||||||
background: layer
|
background: this.mapBackground
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
map.leafletMap.addCallbackAndRunD(leaflet => {
|
map.leafletMap.addCallbackAndRunD(leaflet => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue