forked from MapComplete/MapComplete
		
	Feature: 360-view, experimenting with photo-sphere-viewer
This commit is contained in:
		
							parent
							
								
									fb4fbe2be3
								
							
						
					
					
						commit
						4a45c650be
					
				
					 7 changed files with 265 additions and 29 deletions
				
			
		
							
								
								
									
										93
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										93
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -15,6 +15,7 @@ | |||
|         "@comunica/core": "^3.0.1", | ||||
|         "@comunica/query-sparql": "^3.0.1", | ||||
|         "@comunica/query-sparql-link-traversal": "^0.3.0", | ||||
|         "@photo-sphere-viewer/equirectangular-tiles-adapter": "^5.12.1", | ||||
|         "@rapideditor/location-conflation": "^1.3.0", | ||||
|         "@rgossiaux/svelte-headlessui": "^1.0.2", | ||||
|         "@rgossiaux/svelte-heroicons": "^0.1.2", | ||||
|  | @ -74,6 +75,7 @@ | |||
|         "panzoom": "^9.4.3", | ||||
|         "papaparse": "^5.5.2", | ||||
|         "pg": "^8.11.3", | ||||
|         "photo-sphere-viewer": "^4.8.1", | ||||
|         "pic4carto": "^2.1.15", | ||||
|         "pluscodes": "^2.6.0", | ||||
|         "pmtiles": "^4.2.1", | ||||
|  | @ -6273,6 +6275,32 @@ | |||
|         "url": "https://opencollective.com/parcel" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@photo-sphere-viewer/core": { | ||||
|       "version": "5.12.1", | ||||
|       "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.12.1.tgz", | ||||
|       "integrity": "sha512-aK+SueXdKOr5FQAMwjxswHaa2OZcpWi4tx5P4fjq1vWEDa8PtdaoSdQaAp3Csmthvd9DlfNDUb6c21fTudzM/w==", | ||||
|       "license": "MIT", | ||||
|       "peer": true, | ||||
|       "dependencies": { | ||||
|         "three": "^0.173.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@photo-sphere-viewer/core/node_modules/three": { | ||||
|       "version": "0.173.0", | ||||
|       "resolved": "https://registry.npmjs.org/three/-/three-0.173.0.tgz", | ||||
|       "integrity": "sha512-AUwVmViIEUgBwxJJ7stnF0NkPpZxx1aZ6WiAbQ/Qq61h6I9UR4grXtZDmO8mnlaNORhHnIBlXJ1uBxILEKuVyw==", | ||||
|       "license": "MIT", | ||||
|       "peer": true | ||||
|     }, | ||||
|     "node_modules/@photo-sphere-viewer/equirectangular-tiles-adapter": { | ||||
|       "version": "5.12.1", | ||||
|       "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/equirectangular-tiles-adapter/-/equirectangular-tiles-adapter-5.12.1.tgz", | ||||
|       "integrity": "sha512-Z9oiPNQwBdkGD1m+bXe0EuuBgdZFzec+d7MKexYgEqzLLukgp1WJ4il+3omMaRP5HAhRVWR5vapVALag+8BmPg==", | ||||
|       "license": "MIT", | ||||
|       "peerDependencies": { | ||||
|         "@photo-sphere-viewer/core": "5.12.1" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/@pkgjs/parseargs": { | ||||
|       "version": "0.11.0", | ||||
|       "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", | ||||
|  | @ -23230,6 +23258,17 @@ | |||
|         "split2": "^4.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/photo-sphere-viewer": { | ||||
|       "version": "4.8.1", | ||||
|       "resolved": "https://registry.npmjs.org/photo-sphere-viewer/-/photo-sphere-viewer-4.8.1.tgz", | ||||
|       "integrity": "sha512-Yl1KZq1adtrajCOrf8Y79Qi4A35DfEu8atL779YOdA9XHoH2l2+sYovejnZlGgUM0hEbTyenRDoyXSy/MtioYg==", | ||||
|       "deprecated": "Use @photo-sphere-viewer/core instead, see https://photo-sphere-viewer.js.org/guide/migration.html", | ||||
|       "license": "MIT", | ||||
|       "dependencies": { | ||||
|         "three": "^0.147.0", | ||||
|         "uevent": "^2.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/pic4carto": { | ||||
|       "version": "2.1.15", | ||||
|       "license": "SEE LICENSE IN LICENSE.txt", | ||||
|  | @ -26708,6 +26747,12 @@ | |||
|         "node": ">=0.8" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/three": { | ||||
|       "version": "0.147.0", | ||||
|       "resolved": "https://registry.npmjs.org/three/-/three-0.147.0.tgz", | ||||
|       "integrity": "sha512-LPTOslYQXFkmvceQjFTNnVVli2LaVF6C99Pv34fJypp8NbQLbTlu3KinZ0zURghS5zEehK+VQyvWuPZ/Sm8fzw==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/through": { | ||||
|       "version": "2.3.8", | ||||
|       "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", | ||||
|  | @ -27594,6 +27639,12 @@ | |||
|         "node": ">=4.2.0" | ||||
|       } | ||||
|     }, | ||||
|     "node_modules/uevent": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/uevent/-/uevent-2.2.0.tgz", | ||||
|       "integrity": "sha512-48s5LF/c6R1fUmctGib/dWKhZjZLd4aK/85dwVAbwgHNBSO0k0UNp0ZKZpkSbU6633qYhgykYQPakTSuOxZopA==", | ||||
|       "license": "MIT" | ||||
|     }, | ||||
|     "node_modules/uglify-js": { | ||||
|       "version": "3.19.3", | ||||
|       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", | ||||
|  | @ -34147,6 +34198,29 @@ | |||
|       "version": "2.8.2", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "@photo-sphere-viewer/core": { | ||||
|       "version": "5.12.1", | ||||
|       "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.12.1.tgz", | ||||
|       "integrity": "sha512-aK+SueXdKOr5FQAMwjxswHaa2OZcpWi4tx5P4fjq1vWEDa8PtdaoSdQaAp3Csmthvd9DlfNDUb6c21fTudzM/w==", | ||||
|       "peer": true, | ||||
|       "requires": { | ||||
|         "three": "^0.173.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "three": { | ||||
|           "version": "0.173.0", | ||||
|           "resolved": "https://registry.npmjs.org/three/-/three-0.173.0.tgz", | ||||
|           "integrity": "sha512-AUwVmViIEUgBwxJJ7stnF0NkPpZxx1aZ6WiAbQ/Qq61h6I9UR4grXtZDmO8mnlaNORhHnIBlXJ1uBxILEKuVyw==", | ||||
|           "peer": true | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "@photo-sphere-viewer/equirectangular-tiles-adapter": { | ||||
|       "version": "5.12.1", | ||||
|       "resolved": "https://registry.npmjs.org/@photo-sphere-viewer/equirectangular-tiles-adapter/-/equirectangular-tiles-adapter-5.12.1.tgz", | ||||
|       "integrity": "sha512-Z9oiPNQwBdkGD1m+bXe0EuuBgdZFzec+d7MKexYgEqzLLukgp1WJ4il+3omMaRP5HAhRVWR5vapVALag+8BmPg==", | ||||
|       "requires": {} | ||||
|     }, | ||||
|     "@pkgjs/parseargs": { | ||||
|       "version": "0.11.0", | ||||
|       "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", | ||||
|  | @ -46355,6 +46429,15 @@ | |||
|         "split2": "^4.1.0" | ||||
|       } | ||||
|     }, | ||||
|     "photo-sphere-viewer": { | ||||
|       "version": "4.8.1", | ||||
|       "resolved": "https://registry.npmjs.org/photo-sphere-viewer/-/photo-sphere-viewer-4.8.1.tgz", | ||||
|       "integrity": "sha512-Yl1KZq1adtrajCOrf8Y79Qi4A35DfEu8atL779YOdA9XHoH2l2+sYovejnZlGgUM0hEbTyenRDoyXSy/MtioYg==", | ||||
|       "requires": { | ||||
|         "three": "^0.147.0", | ||||
|         "uevent": "^2.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "pic4carto": { | ||||
|       "version": "2.1.15", | ||||
|       "requires": { | ||||
|  | @ -48749,6 +48832,11 @@ | |||
|         "thenify": ">= 3.1.0 < 4" | ||||
|       } | ||||
|     }, | ||||
|     "three": { | ||||
|       "version": "0.147.0", | ||||
|       "resolved": "https://registry.npmjs.org/three/-/three-0.147.0.tgz", | ||||
|       "integrity": "sha512-LPTOslYQXFkmvceQjFTNnVVli2LaVF6C99Pv34fJypp8NbQLbTlu3KinZ0zURghS5zEehK+VQyvWuPZ/Sm8fzw==" | ||||
|     }, | ||||
|     "through": { | ||||
|       "version": "2.3.8", | ||||
|       "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", | ||||
|  | @ -49436,6 +49524,11 @@ | |||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", | ||||
|       "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" | ||||
|     }, | ||||
|     "uevent": { | ||||
|       "version": "2.2.0", | ||||
|       "resolved": "https://registry.npmjs.org/uevent/-/uevent-2.2.0.tgz", | ||||
|       "integrity": "sha512-48s5LF/c6R1fUmctGib/dWKhZjZLd4aK/85dwVAbwgHNBSO0k0UNp0ZKZpkSbU6633qYhgykYQPakTSuOxZopA==" | ||||
|     }, | ||||
|     "uglify-js": { | ||||
|       "version": "3.19.3", | ||||
|       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", | ||||
|  |  | |||
|  | @ -177,6 +177,7 @@ | |||
|     "@comunica/core": "^3.0.1", | ||||
|     "@comunica/query-sparql": "^3.0.1", | ||||
|     "@comunica/query-sparql-link-traversal": "^0.3.0", | ||||
|     "@photo-sphere-viewer/equirectangular-tiles-adapter": "^5.12.1", | ||||
|     "@rapideditor/location-conflation": "^1.3.0", | ||||
|     "@rgossiaux/svelte-headlessui": "^1.0.2", | ||||
|     "@rgossiaux/svelte-heroicons": "^0.1.2", | ||||
|  | @ -236,6 +237,7 @@ | |||
|     "panzoom": "^9.4.3", | ||||
|     "papaparse": "^5.5.2", | ||||
|     "pg": "^8.11.3", | ||||
|     "photo-sphere-viewer": "^4.8.1", | ||||
|     "pic4carto": "^2.1.15", | ||||
|     "pluscodes": "^2.6.0", | ||||
|     "pmtiles": "^4.2.1", | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								public/assets/loader_base.jpg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/assets/loader_base.jpg
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 145 KiB | 
|  | @ -325,7 +325,7 @@ class MapillaryFetcher implements ImageFetcher { | |||
|     private readonly end_captured_at?: Date | ||||
| 
 | ||||
|     constructor(options?: { | ||||
|         panoramas: undefined | "only" | "no" | ||||
|         panoramas?: undefined | "only" | "no" | ||||
|         max_images?: 100 | number | ||||
|         start_captured_at?: Date | ||||
|         end_captured_at?: Date | ||||
|  | @ -411,7 +411,6 @@ export class CombinedFetcher { | |||
|             new ImagesFromPanoramaxFetcher(), | ||||
|             new ImagesFromPanoramaxFetcher(Constants.panoramax.url), | ||||
|             new MapillaryFetcher({ | ||||
|                 panoramas: "no", | ||||
|                 max_images: 25, | ||||
|                 start_captured_at: maxage, | ||||
|             }), | ||||
|  |  | |||
							
								
								
									
										54
									
								
								src/UI/Image/photoAdapter.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/UI/Image/photoAdapter.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| import { | ||||
|     EquirectangularTilesAdapter, | ||||
|     EquirectangularTilesAdapterConfig | ||||
| } from "@photo-sphere-viewer/equirectangular-tiles-adapter" | ||||
| 
 | ||||
| export class PhotoAdapter extends EquirectangularTilesAdapter { | ||||
|     // This code was shamelessly stolen from https://gitlab.com/panoramax/clients/web-viewer/-/blob/develop/src/utils/PhotoAdapter.js
 | ||||
|     // MIT-license; thank you adrien!
 | ||||
| 
 | ||||
|     private readonly _shouldGoFast: () => boolean | ||||
| 
 | ||||
|     constructor(viewer, config?: EquirectangularTilesAdapterConfig & { shouldGoFast?: () => boolean }) { | ||||
|         super(viewer, config) | ||||
|         this._shouldGoFast = config?.shouldGoFast ?? (() => true) | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Override to skip loading SD images according to shouldGoFast option. | ||||
|      */ | ||||
|     public async loadTexture(panorama, loader) { | ||||
|         if (!panorama.origBaseUrl) { | ||||
|             panorama.origBaseUrl = panorama.baseUrl | ||||
|         } else { | ||||
|             panorama.baseUrl = panorama.origBaseUrl | ||||
|         } | ||||
| 
 | ||||
|         // Fast mode + thumbnail available + no HD image loaded yet + flat picture
 | ||||
|         if ( | ||||
|             this._shouldGoFast() | ||||
|             && panorama.thumbUrl | ||||
|             && !panorama.hdLoaded | ||||
|             && panorama.rows == 1 | ||||
|         ) { | ||||
|             panorama.baseUrl = panorama.thumbUrl | ||||
|         } | ||||
| 
 | ||||
|         let data = await super.loadTexture(panorama, loader) | ||||
|         if (panorama.baseUrl === panorama.origBaseUrl) { | ||||
|             panorama.hdLoaded = true | ||||
|         } | ||||
|         return data | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Override to skip loading tiles according to shouldGoFast option. | ||||
|      * @private | ||||
|      */ | ||||
|     /* | ||||
|    private __loadTiles(tiles) { | ||||
|         if (!this._shouldGoFast()) { | ||||
|             super.__loadTiles(tiles) | ||||
|         } | ||||
|     }*/ | ||||
| } | ||||
|  | @ -1,34 +1,113 @@ | |||
| <script lang="ts"> | ||||
|   import { GeoLocationState } from "../Logic/State/GeoLocationState" | ||||
| 
 | ||||
|   let origlog = console.log | ||||
|   import { onMount } from "svelte" | ||||
| 
 | ||||
|   let logs: string[] = [] | ||||
|   export let imageInfo | ||||
|   // Tiles of the panorama, not geotiles | ||||
|   let tilemeta = imageInfo?.asset_templates?.tiles_webp || imageInfo?.asset_templates?.tiles | ||||
| 
 | ||||
|   function log(...items) { | ||||
|     origlog(...items) | ||||
|     logs.push(items.join(" ")) | ||||
|   import "@photo-sphere-viewer/core/index.css" | ||||
|   // import "@photo-sphere-viewer/virtual-tour-plugin/index.css" | ||||
|   // import "@photo-sphere-viewertileUrl/gallery-plugin/index.css" | ||||
|   // import "@photo-sphere-viewer/markers-plugin/index.css" | ||||
| 
 | ||||
| 
 | ||||
|   import { AbstractAdapter, Viewer as PSViewer } from "photo-sphere-viewer" | ||||
|   import { PhotoAdapter } from "./Image/photoAdapter" | ||||
| 
 | ||||
|   export const PSV_DEFAULT_ZOOM = 30 | ||||
|   export const PSV_ANIM_DURATION = 250 | ||||
|   export const PIC_MAX_STAY_DURATION = 3000 | ||||
| 
 | ||||
|   const BASE_PANORAMA = { | ||||
|     baseUrl: "./assets/loader_base.jpg", | ||||
|     width: 1280, | ||||
|     cols: 2, | ||||
|     rows: 1, | ||||
|     tileUrl: () => null | ||||
|   } | ||||
| 
 | ||||
|   console.log = log | ||||
|   console.error = (...items) => log("ERR: ", ...items) | ||||
|   console.warn = (...items) => log("WARN: ", ...items) | ||||
| 
 | ||||
|   const st = new GeoLocationState() | ||||
|   const av = st.gpsAvailable | ||||
|   const loc = st.currentGPSLocation | ||||
|   const permission = st.permission | ||||
|   let container: HTMLElement | ||||
| 
 | ||||
|   let isSmall = () => container?.offsetWidth < 576 | ||||
|   let shouldGoFast = () => true | ||||
| 
 | ||||
|   function constructPanoramaInfo() { | ||||
|     const f = imageInfo | ||||
| 
 | ||||
|     const hdUrl = (Object.values(f.assets).find(a => a?.roles?.includes("data")) || {}).href | ||||
|     const matrix = f?.properties?.["tiles:tile_matrix_sets"]?.geovisio | ||||
|     const baseUrlWebp = Object.values(f.assets).find(a => a.roles?.includes("visual") && a.type === "image/webp") | ||||
|     const baseUrlJpeg = Object.values(f.assets).find(a => a.roles?.includes("visual") && a.type === "image/jpeg") | ||||
|     const baseUrl = (baseUrlWebp || baseUrlJpeg).href | ||||
|     const thumbUrl = (Object.values(f.assets).find(a => a.roles?.includes("thumbnail") && a.type === "image/jpeg"))?.href | ||||
| 
 | ||||
|     let panorama = { | ||||
|       baseUrl, | ||||
|       origBaseUrl: baseUrl, | ||||
|       basePanoData: (img) => ({ | ||||
|         fullWidth: img.width, | ||||
|         fullHeight: img.height | ||||
|       }), | ||||
|       hdUrl, | ||||
|       thumbUrl, | ||||
|       cols: matrix && matrix.tileMatrix[0].matrixWidth, | ||||
|       rows: matrix && matrix.tileMatrix[0].matrixHeight, | ||||
|       width: matrix && (matrix.tileMatrix[0].matrixWidth * matrix.tileMatrix[0].tileWidth), | ||||
|       tileUrl: matrix && ((col, row) => tilemeta.href.replace(/\{TileCol}/g, col).replace(/\{TileRow}/g, row)) | ||||
|     } | ||||
|     return panorama | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
|   PSViewer["useNewAnglesOrder"] = true | ||||
| 
 | ||||
|   onMount(() => { | ||||
|     const viewer = new PSViewer({ | ||||
|       container, | ||||
| 
 | ||||
|       panorama: BASE_PANORAMA.baseUrl, | ||||
| 
 | ||||
|       adapter: [{ PhotoAdapter, prototype: AbstractAdapter } | ||||
|         , { | ||||
|           showErrorTile: false, | ||||
|           baseBlur: false, | ||||
|           resolution: isSmall() ? 32 : 64 | ||||
|           // shouldGoFast | ||||
|         }], | ||||
| 
 | ||||
|       //withCredentials: parent._options?.fetchOptions?.credentials == "include", | ||||
|       //requestHeaders: parent._options?.fetchOptions?.headers, | ||||
|       //lang: parent._t.psv, | ||||
|       minFov: 5, | ||||
|       loadingTxt: " ", | ||||
|       navbar: null | ||||
|     }) | ||||
| 
 | ||||
| 
 | ||||
|     const panorama = constructPanoramaInfo() | ||||
|     console.log(panorama, container) | ||||
| 
 | ||||
|     viewer.setOptions({ | ||||
|       adapter: [PhotoAdapter, { | ||||
|         showErrorTile: false, | ||||
|         baseBlur: false, | ||||
|         resolution: isSmall() ? 32 : 64 | ||||
|       }] | ||||
|     }) | ||||
|     viewer.setPanorama(panorama.hdUrl, { | ||||
|       zoom: 0, longitude: 45, latitude: -45 | ||||
|     }) | ||||
| 
 | ||||
|     window.setTimeout(() => { | ||||
|       console.log(viewer.getPosition()) | ||||
|     }, 2000) | ||||
| 
 | ||||
|   }) | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| <button on:click={() => st.requestPermission()}>Get geolocation</button> | ||||
| Permission: | ||||
| <code>{$permission}</code> | ||||
| Available: | ||||
| <code>{$av}</code> | ||||
| Location: | ||||
| <code>{JSON.stringify($loc)}</code> | ||||
| <ol> | ||||
|   {#each logs as log} | ||||
|     <li>{log}</li> | ||||
|   {/each} | ||||
| </ol> | ||||
| 
 | ||||
| <div bind:this={container} class="h-screen w-screen"></div> | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										13
									
								
								src/test.ts
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								src/test.ts
									
										
									
									
									
								
							|  | @ -1,4 +1,13 @@ | |||
| import Test from "./UI/Test.svelte" | ||||
| import { OsmConnection } from "./Logic/Osm/OsmConnection" | ||||
| import { ImageData, PanoramaxXYZ } from "panoramax-js" | ||||
| 
 | ||||
| const target = document.getElementById("maindiv") | ||||
| target.innerHTML = "" | ||||
| let img = "https://panoramax-storage-public-fast.s3.gra.perf.cloud.ovh.net/main-pictures/d2/8c/ba/cf/c807-4dbf-b8c8-b1c3aa89182d.jpg" | ||||
| let imgId = "d28cbacf-c807-4dbf-b8c8-b1c3aa89182d" | ||||
| let panoramax = new PanoramaxXYZ() | ||||
| panoramax.imageInfo(imgId).then((imageInfo: ImageData) => { | ||||
|     console.log("IMG INFO: ", imageInfo) | ||||
|     new Test({ target, props: { imageInfo } }) | ||||
| }) | ||||
| 
 | ||||
| new OsmConnection().interact("user/details.json").then((r) => console.log(">>>", r)) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue