forked from MapComplete/MapComplete
Add search previews on the map
This commit is contained in:
parent
1c46a65c84
commit
4f52483a98
19 changed files with 315 additions and 87 deletions
|
|
@ -7,23 +7,17 @@
|
|||
import { LastClickFeatureSource } from "../../Logic/FeatureSource/Sources/LastClickFeatureSource"
|
||||
import Loading from "./Loading.svelte"
|
||||
import { onDestroy } from "svelte"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import { GeocodingUtils } from "../../Logic/Geocoding/GeocodingProvider"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
|
||||
export let state: SpecialVisualizationState
|
||||
export let selected: Feature
|
||||
let tags = state.featureProperties.getStore(selected.properties.id)
|
||||
|
||||
export let absolute = true
|
||||
function getLayer(properties: Record<string, string>) {
|
||||
if (properties.id === "settings") {
|
||||
return UserRelatedState.usersettingsConfig
|
||||
}
|
||||
if (properties.id.startsWith(LastClickFeatureSource.newPointElementId)) {
|
||||
return state.layout.layers.find((l) => l.id === "last_click")
|
||||
}
|
||||
if (properties.id === "location_track") {
|
||||
return state.layout.layers.find((l) => l.id === "gps_track")
|
||||
}
|
||||
return state.layout.getMatchingLayer(properties)
|
||||
function getLayer(properties: Record<string, string>): LayerConfig {
|
||||
return state.getMatchingLayer(properties)
|
||||
}
|
||||
|
||||
let layer = getLayer(selected.properties)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { Store, Stores, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import type { Feature } from "geojson"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Loading from "../Base/Loading.svelte"
|
||||
|
|
@ -17,10 +17,14 @@
|
|||
import type GeocodingProvider from "../../Logic/Geocoding/GeocodingProvider"
|
||||
|
||||
import SearchResults from "./SearchResults.svelte"
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
||||
import MoreScreen from "./MoreScreen"
|
||||
import type { MinimalLayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { focusWithArrows } from "../../Utils/focusWithArrows"
|
||||
import ShowDataLayer from "../Map/ShowDataLayer"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import GeocodingFeatureSource from "../../Logic/Geocoding/GeocodingFeatureSource"
|
||||
import type { LayerConfigJson } from "../../Models/ThemeConfig/Json/LayerConfigJson.js"
|
||||
|
||||
export let perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer> | undefined = undefined
|
||||
export let bounds: UIEventSource<BBox>
|
||||
|
|
@ -29,11 +33,11 @@
|
|||
export let geolocationState: GeoLocationState | undefined = undefined
|
||||
export let clearAfterView: boolean = true
|
||||
export let searcher: GeocodingProvider = new NominatimGeocoding()
|
||||
export let state: SpecialVisualizationState
|
||||
export let state: ThemeViewState
|
||||
let searchContents: UIEventSource<string> = new UIEventSource<string>("")
|
||||
export let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined)
|
||||
onDestroy(
|
||||
triggerSearch.addCallback((_) => {
|
||||
triggerSearch.addCallback(() => {
|
||||
performSearch()
|
||||
})
|
||||
)
|
||||
|
|
@ -139,7 +143,18 @@
|
|||
if (search.length === 0) {
|
||||
return undefined
|
||||
}
|
||||
return searcher.suggest(search, { bbox: bounds.data })
|
||||
return Stores.holdDefined(bounds.bindD(bbox => searcher.suggest(search, { bbox, limit: 15 })))
|
||||
}
|
||||
)
|
||||
let geocededFeatures= new GeocodingFeatureSource(suggestions.stabilized(250))
|
||||
state.featureProperties.trackFeatureSource(geocededFeatures)
|
||||
|
||||
new ShowDataLayer(
|
||||
state.map,
|
||||
{
|
||||
layer: GeocodingUtils.searchLayer,
|
||||
features: geocededFeatures,
|
||||
selectedElement: state.selectedElement
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -147,19 +162,18 @@
|
|||
|
||||
function checkFocus() {
|
||||
window.requestAnimationFrame(() => {
|
||||
if (geosearch.contains(document.activeElement)) {
|
||||
if (geosearch?.contains(document.activeElement)) {
|
||||
return
|
||||
}
|
||||
isFocused.setData(false)
|
||||
})
|
||||
}
|
||||
|
||||
document.addEventListener("focus",() => {
|
||||
document.addEventListener("focus", () => {
|
||||
checkFocus()
|
||||
}, true /* use 'capturing' instead of bubbling, needed for focus-events*/)
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div bind:this={geosearch} use:focusWithArrows={"searchresult"}>
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
import BuildingOffice2 from "@babeard/svelte-heroicons/outline/BuildingOffice2"
|
||||
import Train from "../../assets/svg/Train.svelte"
|
||||
import Airport from "../../assets/svg/Airport.svelte"
|
||||
import BuildingStorefront from "@babeard/svelte-heroicons/outline/BuildingStorefront"
|
||||
|
||||
/**
|
||||
* Renders a single icon.
|
||||
|
|
@ -159,6 +160,8 @@
|
|||
<Train {color} class={clss}/>
|
||||
{:else if icon === "airport"}
|
||||
<Airport {color} class={clss}/>
|
||||
{:else if icon === "building_storefront"}
|
||||
<BuildingStorefront {color} class={clss}/>
|
||||
{:else if Utils.isEmoji(icon)}
|
||||
<span style={`font-size: ${emojiHeight}px; line-height: ${emojiHeight}px`}>
|
||||
{icon}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import LayoutConfig, { MinimalLayoutInformation } from "../Models/ThemeConfig/La
|
|||
import {
|
||||
FeatureSource,
|
||||
IndexedFeatureSource,
|
||||
WritableFeatureSource,
|
||||
WritableFeatureSource
|
||||
} from "../Logic/FeatureSource/FeatureSource"
|
||||
import { OsmConnection } from "../Logic/Osm/OsmConnection"
|
||||
import { Changes } from "../Logic/Osm/Changes"
|
||||
|
|
@ -97,8 +97,10 @@ export interface SpecialVisualizationState {
|
|||
readonly geolocation: GeoLocationHandler
|
||||
readonly recentlySearched: RecentSearch
|
||||
|
||||
getMatchingLayer(properties: Record<string, string>);
|
||||
|
||||
showCurrentLocationOn(map: Store<MlMap>): ShowDataLayer
|
||||
|
||||
reportError(message: string): Promise<void>
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +136,7 @@ export interface SpecialVisualization {
|
|||
export type RenderingSpecification =
|
||||
| string
|
||||
| {
|
||||
func: SpecialVisualization
|
||||
args: string[]
|
||||
style: string
|
||||
}
|
||||
func: SpecialVisualization
|
||||
args: string[]
|
||||
style: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
EyeIcon,
|
||||
HeartIcon,
|
||||
MenuIcon,
|
||||
XCircleIcon,
|
||||
XCircleIcon
|
||||
} from "@rgossiaux/svelte-heroicons/solid"
|
||||
import Tr from "./Base/Tr.svelte"
|
||||
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
|
||||
|
|
@ -72,6 +72,7 @@
|
|||
import HotkeyTable from "./BigComponents/HotkeyTable.svelte"
|
||||
import SelectedElementPanel from "./Base/SelectedElementPanel.svelte"
|
||||
import type { LayerConfigJson } from "../Models/ThemeConfig/Json/LayerConfigJson"
|
||||
import { GeocodingUtils } from "../Logic/Geocoding/GeocodingProvider"
|
||||
|
||||
export let state: ThemeViewState
|
||||
let layout = state.layout
|
||||
|
|
@ -98,22 +99,10 @@
|
|||
})
|
||||
|
||||
let selectedLayer: Store<LayerConfig> = state.selectedElement.mapD((element) => {
|
||||
const id = element.properties.id
|
||||
if (id.startsWith("current_view")) {
|
||||
if (element.properties.id.startsWith("current_view")) {
|
||||
return currentViewLayer
|
||||
}
|
||||
if (id.startsWith("summary_")) {
|
||||
console.log("Not selecting a summary object. The summary object is", element)
|
||||
return undefined
|
||||
}
|
||||
if (id.startsWith(LastClickFeatureSource.newPointElementId)) {
|
||||
return layout.layers.find((l) => l.id === "last_click")
|
||||
}
|
||||
if (id === "location_track") {
|
||||
return layout.layers.find((l) => l.id === "gps_track")
|
||||
}
|
||||
|
||||
return state.layout.getMatchingLayer(element.properties)
|
||||
return state.getMatchingLayer(element.properties)
|
||||
})
|
||||
let currentZoom = state.mapProperties.zoom
|
||||
let showCrosshair = state.userRelatedState.showCrosshair
|
||||
|
|
@ -144,7 +133,7 @@
|
|||
const bottomRight = mlmap.unproject([rect.right, rect.bottom])
|
||||
const bbox = new BBox([
|
||||
[topLeft.lng, topLeft.lat],
|
||||
[bottomRight.lng, bottomRight.lat],
|
||||
[bottomRight.lng, bottomRight.lat]
|
||||
])
|
||||
state.visualFeedbackViewportBounds.setData(bbox)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue