forked from MapComplete/MapComplete
Feature(360): actually show spheres when it is already linked
This commit is contained in:
parent
3e4708b0b9
commit
e81b0d10ea
17 changed files with 124 additions and 30 deletions
18
assets/svg/Panorama360.svg
Normal file
18
assets/svg/Panorama360.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 6.4 KiB |
2
assets/svg/Panorama360.svg.license
Normal file
2
assets/svg/Panorama360.svg.license
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
SPDX-FileCopyrightText: Pieter Vander Vennet
|
||||||
|
SPDX-License-Identifier: CC0-1.0
|
|
@ -1,4 +1,12 @@
|
||||||
[
|
[
|
||||||
|
{
|
||||||
|
"path": "Panorama360.svg",
|
||||||
|
"license": "CC0-1.0",
|
||||||
|
"authors": [
|
||||||
|
"Pieter Vander Vennet"
|
||||||
|
],
|
||||||
|
"sources": []
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "SocialImageForeground.svg",
|
"path": "SocialImageForeground.svg",
|
||||||
"license": "CC-BY-SA-4.0",
|
"license": "CC-BY-SA-4.0",
|
||||||
|
|
|
@ -3354,6 +3354,11 @@ input[type="range"].range-lg::-moz-range-thumb {
|
||||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)) !important;
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1)) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-black {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-blue-100 {
|
.bg-blue-100 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(225 239 254 / var(--tw-bg-opacity, 1));
|
background-color: rgb(225 239 254 / var(--tw-bg-opacity, 1));
|
||||||
|
@ -4015,6 +4020,10 @@ input[type="range"].range-lg::-moz-range-thumb {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-\[3\.25rem\] {
|
||||||
|
padding: 3.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.\!px-0 {
|
.\!px-0 {
|
||||||
padding-left: 0px !important;
|
padding-left: 0px !important;
|
||||||
padding-right: 0px !important;
|
padding-right: 0px !important;
|
||||||
|
|
|
@ -20,7 +20,7 @@ export interface ProvidedImage {
|
||||||
lat?: number
|
lat?: number
|
||||||
lon?: number
|
lon?: number
|
||||||
host?: string
|
host?: string
|
||||||
isSpherical?: boolean
|
isSpherical: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PanoramaView {
|
export interface PanoramaView {
|
||||||
|
|
|
@ -32,6 +32,7 @@ export class Imgur extends ImageProvider {
|
||||||
key: key,
|
key: key,
|
||||||
provider: this,
|
provider: this,
|
||||||
id: value,
|
id: value,
|
||||||
|
isSpherical: false
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,19 +204,24 @@ export class Mapillary extends ImageProvider {
|
||||||
const metadataUrl =
|
const metadataUrl =
|
||||||
"https://graph.mapillary.com/" +
|
"https://graph.mapillary.com/" +
|
||||||
mapillaryId +
|
mapillaryId +
|
||||||
"?fields=thumb_1024_url,thumb_original_url,captured_at,compass_angle,geometry,creator,camera_type&access_token=" +
|
"?fields=thumb_1024_url,thumb_original_url,captured_at,compass_angle,geometry,computed_geometry,creator,camera_type&access_token=" +
|
||||||
Constants.mapillary_client_token_v4
|
Constants.mapillary_client_token_v4
|
||||||
const response = await Utils.downloadJsonCached<{
|
const response = await Utils.downloadJsonCached<{
|
||||||
thumb_1024_url: string, thumb_original_url: string, captured_at,
|
thumb_1024_url: string,
|
||||||
|
thumb_original_url: string,
|
||||||
|
captured_at,
|
||||||
compass_angle: number,
|
compass_angle: number,
|
||||||
creator: string
|
creator: string,
|
||||||
|
computed_geometry: Point,
|
||||||
|
geometry: Point,
|
||||||
|
camera_type: "equirectangular" | "spherical" | string
|
||||||
}>(metadataUrl, 60 * 60)
|
}>(metadataUrl, 60 * 60)
|
||||||
const url = <string>response["thumb_1024_url"]
|
const url = <string>response["thumb_1024_url"]
|
||||||
const url_hd = <string>response["thumb_original_url"]
|
const url_hd = <string>response["thumb_original_url"]
|
||||||
const date = new Date()
|
const date = new Date()
|
||||||
const rotation = (720 - Number(response["compass_angle"])) % 360
|
const rotation: number = (720 - Number(response.compass_angle)) % 360
|
||||||
const geometry = response["geometry"]
|
const geometry: Point = response.computed_geometry ?? response.geometry
|
||||||
date.setTime(response["captured_at"])
|
date.setTime(response.captured_at)
|
||||||
return <ProvidedImage>{
|
return <ProvidedImage>{
|
||||||
id: "" + mapillaryId,
|
id: "" + mapillaryId,
|
||||||
url,
|
url,
|
||||||
|
@ -225,6 +230,7 @@ export class Mapillary extends ImageProvider {
|
||||||
date,
|
date,
|
||||||
key,
|
key,
|
||||||
rotation,
|
rotation,
|
||||||
|
isSpherical: response.camera_type === "spherical" || response.camera_type === "equirectangular",
|
||||||
lat: geometry.coordinates[1],
|
lat: geometry.coordinates[1],
|
||||||
lon: geometry.coordinates[0]
|
lon: geometry.coordinates[0]
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@ export default class PanoramaxImageProvider extends ImageProvider {
|
||||||
provider: this,
|
provider: this,
|
||||||
status: meta.properties["geovisio:status"],
|
status: meta.properties["geovisio:status"],
|
||||||
rotation: Number(meta.properties["view:azimuth"]),
|
rotation: Number(meta.properties["view:azimuth"]),
|
||||||
|
isSpherical: meta.properties.exif["Xmp.GPano.ProjectionType"] === "equirectangular",
|
||||||
date: new Date(meta.properties.datetime),
|
date: new Date(meta.properties.datetime),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
import ImageProvider, { ProvidedImage } from "./ImageProvider"
|
import ImageProvider, { PanoramaView, ProvidedImage } from "./ImageProvider"
|
||||||
import BaseUIElement from "../../UI/BaseUIElement"
|
import BaseUIElement from "../../UI/BaseUIElement"
|
||||||
import { WikimediaImageProvider } from "./WikimediaImageProvider"
|
import { WikimediaImageProvider } from "./WikimediaImageProvider"
|
||||||
import Wikidata from "../Web/Wikidata"
|
import Wikidata from "../Web/Wikidata"
|
||||||
import SvelteUIElement from "../../UI/Base/SvelteUIElement"
|
import SvelteUIElement from "../../UI/Base/SvelteUIElement"
|
||||||
import * as Wikidata_icon from "../../assets/svg/Wikidata.svelte"
|
import * as Wikidata_icon from "../../assets/svg/Wikidata.svelte"
|
||||||
import { Utils } from "../../Utils"
|
import { Utils } from "../../Utils"
|
||||||
|
import { Feature, Point } from "geojson"
|
||||||
|
|
||||||
export class WikidataImageProvider extends ImageProvider {
|
export class WikidataImageProvider extends ImageProvider {
|
||||||
|
|
||||||
|
|
||||||
public static readonly singleton = new WikidataImageProvider()
|
public static readonly singleton = new WikidataImageProvider()
|
||||||
public readonly defaultKeyPrefixes = ["wikidata"]
|
public readonly defaultKeyPrefixes = ["wikidata"]
|
||||||
public readonly name = "Wikidata"
|
public readonly name = "Wikidata"
|
||||||
private static readonly keyBlacklist: ReadonlySet<string> = new Set([
|
private static readonly keyBlacklist: ReadonlySet<string> = new Set([
|
||||||
"mapillary",
|
"mapillary",
|
||||||
...Utils.Times((i) => "mapillary:" + i, 10),
|
...Utils.Times((i) => "mapillary:" + i, 10)
|
||||||
])
|
])
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
|
@ -66,4 +69,8 @@ export class WikidataImageProvider extends ImageProvider {
|
||||||
public DownloadAttribution(): Promise<undefined> {
|
public DownloadAttribution(): Promise<undefined> {
|
||||||
throw new Error("Method not implemented; shouldn't be needed!")
|
throw new Error("Method not implemented; shouldn't be needed!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPanoramaInfo(image: { id: string }): Promise<Feature<Point, PanoramaView>> {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import ImageProvider, { ProvidedImage } from "./ImageProvider"
|
import ImageProvider, { PanoramaView, ProvidedImage } from "./ImageProvider"
|
||||||
import BaseUIElement from "../../UI/BaseUIElement"
|
import BaseUIElement from "../../UI/BaseUIElement"
|
||||||
import { Utils } from "../../Utils"
|
import { Utils } from "../../Utils"
|
||||||
import { LicenseInfo } from "./LicenseInfo"
|
import { LicenseInfo } from "./LicenseInfo"
|
||||||
import Wikimedia from "../Web/Wikimedia"
|
import Wikimedia from "../Web/Wikimedia"
|
||||||
import SvelteUIElement from "../../UI/Base/SvelteUIElement"
|
import SvelteUIElement from "../../UI/Base/SvelteUIElement"
|
||||||
import Wikimedia_commons_white from "../../assets/svg/Wikimedia_commons_white.svelte"
|
import Wikimedia_commons_white from "../../assets/svg/Wikimedia_commons_white.svelte"
|
||||||
|
import { Feature, Point } from "geojson"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This module provides endpoints for wikimedia and others
|
* This module provides endpoints for wikimedia and others
|
||||||
|
@ -123,7 +124,6 @@ export class WikimediaImageProvider extends ImageProvider {
|
||||||
|
|
||||||
public async DownloadAttribution(img: { url: string }): Promise<LicenseInfo> {
|
public async DownloadAttribution(img: { url: string }): Promise<LicenseInfo> {
|
||||||
const filename = WikimediaImageProvider.ExtractFileName(img.url)
|
const filename = WikimediaImageProvider.ExtractFileName(img.url)
|
||||||
|
|
||||||
if (filename === "") {
|
if (filename === "") {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,11 @@ export class WikimediaImageProvider extends ImageProvider {
|
||||||
key: undefined,
|
key: undefined,
|
||||||
provider: this,
|
provider: this,
|
||||||
id: image,
|
id: image,
|
||||||
|
isSpherical: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPanoramaInfo(image: { id: string }): Promise<Feature<Point, PanoramaView>> | undefined {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,7 +234,7 @@ class MapillaryFetcher implements ImageFetcher {
|
||||||
async fetchImages(lat: number, lon: number): Promise<P4CPicture[]> {
|
async fetchImages(lat: number, lon: number): Promise<P4CPicture[]> {
|
||||||
const boundingBox = new BBox([[lon, lat]]).padAbsolute(0.003)
|
const boundingBox = new BBox([[lon, lat]]).padAbsolute(0.003)
|
||||||
let url =
|
let url =
|
||||||
"https://graph.mapillary.com/images?fields=computed_geometry,creator,id,thumb_256_url,thumb_original_url,compass_angle&bbox=" +
|
"https://graph.mapillary.com/images?fields=geometry,computed_geometry,creator,id,thumb_256_url,thumb_original_url,compass_angle&bbox=" +
|
||||||
[
|
[
|
||||||
boundingBox.getWest(),
|
boundingBox.getWest(),
|
||||||
boundingBox.getSouth(),
|
boundingBox.getSouth(),
|
||||||
|
@ -263,6 +263,7 @@ class MapillaryFetcher implements ImageFetcher {
|
||||||
data: {
|
data: {
|
||||||
id: string
|
id: string
|
||||||
creator: string
|
creator: string
|
||||||
|
geometry: Point
|
||||||
computed_geometry: Point
|
computed_geometry: Point
|
||||||
is_pano: boolean
|
is_pano: boolean
|
||||||
thumb_256_url: string
|
thumb_256_url: string
|
||||||
|
@ -272,7 +273,7 @@ class MapillaryFetcher implements ImageFetcher {
|
||||||
}>(url)
|
}>(url)
|
||||||
const pics: P4CPicture[] = []
|
const pics: P4CPicture[] = []
|
||||||
for (const img of response.data) {
|
for (const img of response.data) {
|
||||||
const c = img.computed_geometry.coordinates
|
const c = img.computed_geometry?.coordinates ?? img.geometry.coordinates
|
||||||
if (img.thumb_original_url === undefined) {
|
if (img.thumb_original_url === undefined) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
import LoadingPlaceholder from "../Base/LoadingPlaceholder.svelte"
|
import LoadingPlaceholder from "../Base/LoadingPlaceholder.svelte"
|
||||||
import { MenuState } from "../../Models/MenuState"
|
import { MenuState } from "../../Models/MenuState"
|
||||||
import ThemeViewState from "../../Models/ThemeViewState"
|
import ThemeViewState from "../../Models/ThemeViewState"
|
||||||
|
import Panorama360 from "../../assets/svg/Panorama360.svelte"
|
||||||
|
|
||||||
export let image: Partial<ProvidedImage> & { id: string; url: string }
|
export let image: Partial<ProvidedImage> & { id: string; url: string }
|
||||||
let fallbackImage: string = undefined
|
let fallbackImage: string = undefined
|
||||||
|
@ -48,7 +49,7 @@
|
||||||
previewedImage.addCallbackAndRun((previewedImage) => {
|
previewedImage.addCallbackAndRun((previewedImage) => {
|
||||||
showBigPreview.set(
|
showBigPreview.set(
|
||||||
previewedImage !== undefined &&
|
previewedImage !== undefined &&
|
||||||
(previewedImage?.id ?? previewedImage?.url) === (image.id ?? image.url)
|
(previewedImage?.id ?? previewedImage?.url) === (image.id ?? image.url)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -66,12 +67,12 @@
|
||||||
type: "Feature",
|
type: "Feature",
|
||||||
properties: {
|
properties: {
|
||||||
id: image.id,
|
id: image.id,
|
||||||
rotation: image.rotation,
|
rotation: image.rotation
|
||||||
},
|
},
|
||||||
geometry: {
|
geometry: {
|
||||||
type: "Point",
|
type: "Point",
|
||||||
coordinates: [image.lon, image.lat],
|
coordinates: [image.lon, image.lat]
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
state?.geocodedImages.set([f])
|
state?.geocodedImages.set([f])
|
||||||
}
|
}
|
||||||
|
@ -100,10 +101,10 @@
|
||||||
<Tr t={Translations.t.image.processing} />
|
<Tr t={Translations.t.image.processing} />
|
||||||
</Loading>
|
</Loading>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else if image.status !== "hidden"}
|
||||||
<div class="relative shrink-0">
|
<div class="relative shrink-0">
|
||||||
<div
|
<div
|
||||||
class="relative w-fit"
|
class={"relative w-fit"}
|
||||||
on:mouseenter={() => highlight()}
|
on:mouseenter={() => highlight()}
|
||||||
on:mouseleave={() => highlight(false)}
|
on:mouseleave={() => highlight(false)}
|
||||||
>
|
>
|
||||||
|
@ -132,6 +133,16 @@
|
||||||
src={image.url}
|
src={image.url}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{#if image.isSpherical}
|
||||||
|
<div class="absolute top-0 left-0 w-full h-full flex justify-center items-center pointer-events-none">
|
||||||
|
<div class="bg-black opacity-50 rounded-full p-[3.25rem]">
|
||||||
|
<div class="w-0 h-0 relative flex items-center justify-center">
|
||||||
|
<Panorama360 class="absolute w-16 h-16" color="#ffffff" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if canZoom && loaded}
|
{#if canZoom && loaded}
|
||||||
<div
|
<div
|
||||||
class="bg-black-transparent absolute right-0 top-0 rounded-bl-full"
|
class="bg-black-transparent absolute right-0 top-0 rounded-bl-full"
|
||||||
|
@ -145,4 +156,7 @@
|
||||||
<ImageAttribution {image} {attributionFormat} />
|
<ImageAttribution {image} {attributionFormat} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{:else if image.status === "hidden"}
|
||||||
|
<div class="subtle">This image has been reported</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
import Popup from "../Base/Popup.svelte"
|
import Popup from "../Base/Popup.svelte"
|
||||||
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
|
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
|
||||||
import NextButton from "../Base/NextButton.svelte"
|
import NextButton from "../Base/NextButton.svelte"
|
||||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||||
import AttributedImage from "./AttributedImage.svelte"
|
import AttributedImage from "./AttributedImage.svelte"
|
||||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
|
||||||
import Dropdown from "../Base/Dropdown.svelte"
|
import Dropdown from "../Base/Dropdown.svelte"
|
||||||
import { REPORT_REASONS, ReportReason } from "panoramax-js"
|
import { REPORT_REASONS, ReportReason } from "panoramax-js"
|
||||||
import { onDestroy } from "svelte"
|
import { onDestroy } from "svelte"
|
||||||
|
@ -19,10 +18,14 @@
|
||||||
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction"
|
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction"
|
||||||
import { Tag } from "../../Logic/Tags/Tag"
|
import { Tag } from "../../Logic/Tags/Tag"
|
||||||
import { MenuState } from "../../Models/MenuState"
|
import { MenuState } from "../../Models/MenuState"
|
||||||
|
import type { Feature } from "geojson"
|
||||||
|
import ThemeViewState from "../../Models/ThemeViewState"
|
||||||
|
|
||||||
export let image: ProvidedImage
|
export let image: ProvidedImage
|
||||||
export let state: SpecialVisualizationState
|
export let state: ThemeViewState
|
||||||
export let tags: UIEventSource<Record<string, string>>
|
export let tags: UIEventSource<Record<string, string>>
|
||||||
|
export let nearbyFeatures: Feature[] | Store<Feature[]> = []
|
||||||
|
|
||||||
let showDeleteDialog = new UIEventSource(false)
|
let showDeleteDialog = new UIEventSource(false)
|
||||||
onDestroy(
|
onDestroy(
|
||||||
showDeleteDialog.addCallbackAndRunD((shown) => {
|
showDeleteDialog.addCallbackAndRunD((shown) => {
|
||||||
|
@ -160,7 +163,7 @@
|
||||||
|
|
||||||
<div class="relative w-fit shrink-0" style="scroll-snap-align: start">
|
<div class="relative w-fit shrink-0" style="scroll-snap-align: start">
|
||||||
<div class="relative flex max-w-max items-center bg-gray-200">
|
<div class="relative flex max-w-max items-center bg-gray-200">
|
||||||
<AttributedImage imgClass="carousel-max-height" {image} {state}>
|
<AttributedImage imgClass="carousel-max-height" {image} {state} {nearbyFeatures}>
|
||||||
<svelte:fragment slot="dot-menu-actions">
|
<svelte:fragment slot="dot-menu-actions">
|
||||||
<button on:click={() => ImageProvider.offerImageAsDownload(image)}>
|
<button on:click={() => ImageProvider.offerImageAsDownload(image)}>
|
||||||
<DownloadIcon />
|
<DownloadIcon />
|
||||||
|
|
|
@ -1,15 +1,30 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Store, UIEventSource } from "../../Logic/UIEventSource.js"
|
import { Store, UIEventSource } from "../../Logic/UIEventSource.js"
|
||||||
import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider"
|
import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider"
|
||||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
|
||||||
import DeletableImage from "./DeletableImage.svelte"
|
import DeletableImage from "./DeletableImage.svelte"
|
||||||
import LoadingPlaceholder from "../Base/LoadingPlaceholder.svelte"
|
import LoadingPlaceholder from "../Base/LoadingPlaceholder.svelte"
|
||||||
|
import type { Feature, Point } from "geojson"
|
||||||
|
import ThemeViewState from "../../Models/ThemeViewState"
|
||||||
|
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||||
|
import { GeoOperations } from "../../Logic/GeoOperations"
|
||||||
|
|
||||||
export let images: Store<ProvidedImage[]>
|
export let images: Store<ProvidedImage[]>
|
||||||
export let state: SpecialVisualizationState
|
export let state: ThemeViewState
|
||||||
export let tags: UIEventSource<Record<string, string>>
|
export let tags: UIEventSource<Record<string, string>>
|
||||||
|
export let feature: Feature
|
||||||
export let estimated: Store<number>
|
export let estimated: Store<number>
|
||||||
|
export let layer: LayerConfig
|
||||||
|
let zoomToFeature: Feature<Point> = {
|
||||||
|
type: "Feature",
|
||||||
|
geometry: {
|
||||||
|
type: "Point",
|
||||||
|
coordinates: GeoOperations.centerpointCoordinates(feature)
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
name: layer?.title?.GetRenderValue(feature.properties)?.Subs(feature.properties)?.txt ?? feature?.properties?.name,
|
||||||
|
focus: true
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $estimated > 0 && $images.length < 1}
|
{#if $estimated > 0 && $images.length < 1}
|
||||||
|
@ -18,7 +33,7 @@
|
||||||
<div class="w-full overflow-x-auto" style="scroll-snap-type: x proximity">
|
<div class="w-full overflow-x-auto" style="scroll-snap-type: x proximity">
|
||||||
<div class="flex space-x-2">
|
<div class="flex space-x-2">
|
||||||
{#each $images as image (image.url)}
|
{#each $images as image (image.url)}
|
||||||
<DeletableImage {image} {state} {tags} />
|
<DeletableImage {image} {state} {tags} nearbyFeatures={[zoomToFeature]} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||||
import Zoomcontrol from "../Zoomcontrol"
|
import Zoomcontrol from "../Zoomcontrol"
|
||||||
import { onDestroy } from "svelte"
|
import { onDestroy } from "svelte"
|
||||||
import type { PanoramaView } from "./photoSphereViewerWrapper"
|
import type { PanoramaView } from "../../Logic/ImageProviders/ImageProvider"
|
||||||
import { PhotoSphereViewerWrapper } from "./photoSphereViewerWrapper"
|
import { PhotoSphereViewerWrapper } from "./photoSphereViewerWrapper"
|
||||||
|
|
||||||
import type { Feature, Point } from "geojson"
|
import type { Feature, Point } from "geojson"
|
||||||
|
|
|
@ -70,7 +70,7 @@ export class ImageVisualisations {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
needsUrls: AllImageProviders.apiUrls,
|
needsUrls: AllImageProviders.apiUrls,
|
||||||
constr: (state, tags, args) => {
|
constr: (state, tags, args, feature) => {
|
||||||
let imagePrefixes: string[] = undefined
|
let imagePrefixes: string[] = undefined
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
imagePrefixes = [].concat(...args.map((a) => a.split(";")))
|
imagePrefixes = [].concat(...args.map((a) => a.split(";")))
|
||||||
|
@ -79,7 +79,7 @@ export class ImageVisualisations {
|
||||||
const estimated = tags.mapD((tags) =>
|
const estimated = tags.mapD((tags) =>
|
||||||
AllImageProviders.estimateNumberOfImages(tags, imagePrefixes)
|
AllImageProviders.estimateNumberOfImages(tags, imagePrefixes)
|
||||||
)
|
)
|
||||||
return new SvelteUIElement(ImageCarousel, { state, tags, images, estimated })
|
return new SvelteUIElement(ImageCarousel, { state, tags, images, estimated, feature })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
4
src/assets/svg/Panorama360.svelte
Normal file
4
src/assets/svg/Panorama360.svelte
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue