From 8d471c449bef61d2c5fb10c83882188adbee7b4c Mon Sep 17 00:00:00 2001 From: Damien Sorel Date: Thu, 3 Mar 2022 13:13:47 +0100 Subject: [PATCH] Close #646 marker: imageLayer orientation and opacity --- docs/plugins/plugin-markers.md | 16 +++++++++++++-- example/assets/target.png | Bin 0 -> 6362 bytes example/plugin-markers.html | 14 ++++++++++++- src/plugins/markers/Marker.js | 34 +++++++++++++++++++++++++++---- types/plugins/markers/index.d.ts | 2 ++ 5 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 example/assets/target.png diff --git a/docs/plugins/plugin-markers.md b/docs/plugins/plugin-markers.md index dbf8795b2..ab922fe6f 100644 --- a/docs/plugins/plugin-markers.md +++ b/docs/plugins/plugin-markers.md @@ -129,6 +129,12 @@ _(This option is ignored for polygons and polylines)._ Size of the marker in pixels. _(This option is ignored for polygons and polylines)._ +#### `orientation` (only for `imageLayer`) +- type: `'front' | 'horizontal' | 'vertical-left' | 'vertical-right'` +- default: `'front'` + +Applies a perspective on the image to make it look like placed on the floor or on a wall. + #### `scale` - type: `double[] | { zoom: double[], longitude: [] }` - default: no scalling @@ -163,17 +169,23 @@ scale: { } ``` +#### `opacity` +- type: `number` +- default: `1` + +Opacity of the marker. (Works for `imageLayer` too). + #### `className` - type: `string` CSS class(es) added to the marker element. -_(This option is ignored for imageLayer markers)._ +_(This option is ignored for `imageLayer` markers)._ #### `style` - type: `object` CSS properties to set on the marker (background, border, etc.). -_(This option is ignored for imageLayer markers)._ +_(This option is ignored for `imageLayer` markers)._ ```js style: { diff --git a/example/assets/target.png b/example/assets/target.png new file mode 100644 index 0000000000000000000000000000000000000000..5cc17283b244ae83a9bca6dafc2605836ba4af61 GIT binary patch literal 6362 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 Level 3 PhotoSphereViewer.GyroscopePlugin, PhotoSphereViewer.StereoPlugin, [PhotoSphereViewer.MarkersPlugin, { - markers : (() => { + markers: (() => { const a = []; // add markers all hover the sphere @@ -271,6 +271,18 @@

Header Level 3

tooltip : 'Image embedded in the scene', }); + a.push({ + id : 'imageLayerOrient', + imageLayer : 'assets/target.png', + width : 120, + height : 120, + latitude : -0.2, + longitude : 0.27, + opacity : 0.8, + orientation: 'horizontal', + tooltip : 'Image embedded in the scene with "horizontal" orientation', + }); + // SVG markers a.push({ id : 'svg-demo', diff --git a/src/plugins/markers/Marker.js b/src/plugins/markers/Marker.js index 1f6f4ffd0..492951ac0 100644 --- a/src/plugins/markers/Marker.js +++ b/src/plugins/markers/Marker.js @@ -395,6 +395,7 @@ export class Marker { } // apply style + this.$el.style.opacity = this.config.opacity ?? 1; if (this.config.style) { utils.deepmerge(this.$el.style, this.config.style); } @@ -627,7 +628,7 @@ export class Marker { // compute x/y/z positions this.props.positions3D = this.props.def.map((coord) => { - return this.psv.dataHelper.sphericalCoordsToVector3({ longitude: coord[0], latitude: coord[1] }); + return this.psv.dataHelper.sphericalCoordsToVector3({ longitude: coord[0], latitude : coord[1] }); }); } @@ -653,7 +654,11 @@ export class Marker { switch (this.type) { case MARKER_TYPES.imageLayer: if (!this.$el) { - const material = new THREE.MeshBasicMaterial({ transparent: true, depthTest: false }); + const material = new THREE.MeshBasicMaterial({ + transparent: true, + opacity : this.config.opacity ?? 1, + depthTest : false, + }); const geometry = new THREE.PlaneGeometry(1, 1); const mesh = new THREE.Mesh(geometry, material); mesh.userData = { [MARKER_DATA]: this }; @@ -676,7 +681,10 @@ export class Marker { if (this.psv.config.requestHeaders && typeof this.psv.config.requestHeaders === 'function') { this.loader.setRequestHeader(this.psv.config.requestHeaders(this.config.imageLayer)); } - this.$el.children[0].material.map = this.loader.load(this.config.imageLayer, () => this.psv.needsUpdate()); + this.$el.children[0].material.map = this.loader.load(this.config.imageLayer, (texture) => { + texture.anisotropy = 4; + this.psv.needsUpdate(); + }); this.props.def = this.config.imageLayer; } @@ -687,7 +695,25 @@ export class Marker { ); this.$el.position.copy(this.props.positions3D[0]); - this.$el.lookAt(0, 0, 0); + + switch (this.config.orientation) { + case 'horizontal': + this.$el.lookAt(0, this.$el.position.y, 0); + this.$el.rotateX(this.props.position.latitude < 0 ? -Math.PI / 2 : Math.PI / 2); + break; + case 'vertical-left': + this.$el.lookAt(0, 0, 0); + this.$el.rotateY(-Math.PI * 0.4); + break; + case 'vertical-right': + this.$el.lookAt(0, 0, 0); + this.$el.rotateY(Math.PI * 0.4); + break; + default: + this.$el.lookAt(0, 0, 0); + break; + } + // 100 is magic number that gives a coherent size at default zoom level this.$el.scale.set(this.config.width / 100 * SYSTEM.pixelRatio, this.config.height / 100 * SYSTEM.pixelRatio, 1); break; diff --git a/types/plugins/markers/index.d.ts b/types/plugins/markers/index.d.ts index 29f2559d8..2416c5329 100644 --- a/types/plugins/markers/index.d.ts +++ b/types/plugins/markers/index.d.ts @@ -35,7 +35,9 @@ export type MarkerProperties = Partial & { id: string; width?: number; height?: number; + orientation?: 'front' | 'horizontal' | 'vertical-left' | 'vertical-right'; scale?: number | [number, number] | { zoom?: [number, number], longitude?: [number, number] }; + opacity?: number; className?: string; style?: Record; svgStyle?: Record;