diff --git a/packages/frontend/src/main/components/common/PreviewImage.vue b/packages/frontend/src/main/components/common/PreviewImage.vue
index 8ef3f83ba..389f92c90 100644
--- a/packages/frontend/src/main/components/common/PreviewImage.vue
+++ b/packages/frontend/src/main/components/common/PreviewImage.vue
@@ -3,22 +3,35 @@
:style="`position: relative; height: ${height}px;`"
:class="`${$vuetify.theme.dark ? 'grey darken-4' : 'grey lighten-4'}`"
@mouseenter="hovered = true"
- @touchmove="parseTouch"
- @mouseleave="
- hovered = false
- imageIndex = 0
- "
+ @mouseleave="hovered = false"
@mousemove="setIndex"
+ @touchmove="
+ (e) =>
+ setIndex({
+ target: e.target,
+ clientX: e.touches[0].clientX,
+ clientY: e.touches[0].clientY
+ })
+ "
>
-
-
+
+
+
+
+
+
@@ -36,7 +49,7 @@ export default {
},
height: {
type: Number,
- default: 180
+ default: 200
},
rotate: {
type: Boolean,
@@ -45,68 +58,97 @@ export default {
},
data() {
return {
+ isMounted: false,
loading: false,
hovered: false,
hasStartedLoadingImages: false,
- currentPreviewImg: '',
- previewImages: [],
+ previewImage: null,
+ fullPreviewImage: null,
imageIndex: 0,
legacyMode: false,
- angles: [
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 0
- ]
+ controller: new AbortController()
}
},
computed: {
- revImg() {
- return this.legacyMode ? this.previewImages : [...this.previewImages].reverse()
+ background() {
+ return `
+ position: absolute;
+ top:0;
+ height: 100%;
+ width: 100%;
+ background-size: cover;
+ background-image:url(${this.previewImage});
+ background-position: center center;
+ `
},
- bgStyle() {
- let bgStyle = `
+ background360() {
+ let background = `
+ position: absolute;
+ opacity: ${!this.legacyMode && this.hovered && this.fullPreviewImage ? 1 : 0};
+ transition: opacity 0.5s;
+ top:0;
height: 100%;
width: 100%;
background-size: cover;
background-image:`
+ if (this.fullPreviewImage && (this.hovered || true)) {
+ background += `url(${this.fullPreviewImage});`
+ } else {
+ background += `url(${this.previewImage});`
+ }
+ if (!this.isMounted) return background
+ const scaleFactor = this.$refs.image_360.getBoundingClientRect().height / 400
+ const actualWidth = scaleFactor * 700
+ const widthDiff =
+ (this.$refs.image_360.getBoundingClientRect().width - actualWidth) * 0.5
- for (let i = 0; i < this.revImg.length; i++) {
- bgStyle += `url(${this.revImg[i]})${i !== this.revImg.length - 1 ? ',' : ';'}`
+ if (this.fullPreviewImage && (this.hovered || true)) {
+ background += `background-position: ${-(
+ actualWidth * (2 * this.imageIndex + 1) -
+ widthDiff
+ )}px 0;`
+ } else {
+ background += `background-position: center center;`
}
- bgStyle += `
- background-position:`
- for (let i = 0; i < this.revImg.length; i++) {
- bgStyle += `${i === this.imageIndex ? 'center' : '10000px'}${
- i !== this.revImg.length - 1 ? ',' : ';'
- }`
- }
- return bgStyle
+ return background
}
},
watch: {
hovered(val) {
- if (!this.rotate) return
- if (!val || this.hasStartedLoadingImages) return
- this.getOtherAngles()
- this.hasStartedLoadingImages = true
+ if (val && !this.fullPreviewImage) {
+ setTimeout(async () => {
+ if (!this.hovered) return
+ if (this.legacyMode) return
+ if (this.fullPreviewImage) return
+ this.loading = true
+ try {
+ this.fullPreviewImage = await this.getPreviewImage('all')
+ } catch (err) {
+ if (err.toString() === 'Failed getting preview') {
+ this.legacyMode = true
+ }
+ // else: we've aborted the request due to mouse moving out
+ }
+ this.loading = false
+ }, 500)
+ }
+
+ if (!val && this.loading) {
+ this.controller.abort()
+ this.controller = new AbortController()
+ this.loading = false
+ }
+ if (!val) {
+ this.imageIndex = 0
+ }
}
},
async mounted() {
- this.previewImages.push(await this.getPreviewImage())
+ this.previewImage = await this.getPreviewImage()
+ this.isMounted = true
},
methods: {
- parseTouch(e) {
- if (this.loading || !this.rotate) {
- this.imageIndex = 0
- return
- }
- this.hovered = true
- this.setIndex({
- target: e.target,
- clientX: e.touches[0].clientX,
- clientY: e.touches[0].clientY
- })
- },
setIndex(e) {
if (this.loading || !this.rotate) {
this.imageIndex = 0
@@ -114,13 +156,14 @@ export default {
}
const rect = e.target.getBoundingClientRect()
const x = e.clientX - rect.left
- const step = rect.width / this.previewImages.length
+ const step = rect.width / 24
let index = Math.round(x / step)
- if (index >= this.previewImages.length) index = this.previewImages.length - 1
+ if (index >= 24) index = 24 - 1
this.imageIndex = index
},
async getPreviewImage(angle = 0) {
const res = await fetch(this.url + `/${angle}`, {
+ signal: this.controller.signal,
headers: localStorage.getItem('AuthToken')
? { Authorization: `Bearer ${localStorage.getItem('AuthToken')}` }
: {}
@@ -131,44 +174,6 @@ export default {
}
const blob = await res.blob()
return URL.createObjectURL(blob)
- },
- async getOtherAngles() {
- // Note: previously, previews were generated for only 5 angles (-30deg, -15, 0, 15, 30deg), corresponding to
- // labelled angles (-2, -1, 0, 1, 2). We have now switched to generating full 360deg previews in increments
- // of 15 deg, going clockwise straight. Eg., 0 = 0deg, 1 = 15deg, 2 = 30 deg, etc.
- this.loading = true
-
- try {
- const img = await this.getPreviewImage(this.angles[this.angles.length - 1]) // note: this throws if requesting an incorrect angle.
- this.$set(this.previewImages, this.angles.length - 1, img)
- const promises = []
-
- for (let i = 1; i < this.angles.length; i++) {
- promises.push(this.getPreviewImage(this.angles[i]))
- }
-
- const otherImgs = await Promise.all(promises)
- for (let i = 0; i < otherImgs.length; i++) {
- this.$set(this.previewImages, i + 1, otherImgs[i])
- }
- } catch (e) {
- // legacy track
- this.legacyMode = true
- const otherImgs = await Promise.all([
- this.getPreviewImage(-1),
- this.getPreviewImage(-2),
- this.getPreviewImage(1),
- this.getPreviewImage(2)
- ])
- this.previewImages.unshift(otherImgs[0])
- this.previewImages.unshift(otherImgs[1])
- this.previewImages.push(otherImgs[2])
- this.previewImages.push(otherImgs[3])
- // TODO: Weird. getPreviewImage throws, but the try block keeps going until the for loop,
- // resulting in an incorrect array; we need to filter out nulls/undefineds here...
- this.previewImages = this.previewImages.filter((i) => !!i)
- }
- this.loading = false
}
}
}
@@ -178,25 +183,4 @@ export default {
transition: all 0.3s;
filter: grayscale(100%);
}
-
-.preview-img {
- width: 100%;
- opacity: 0.8;
- object-fit: cover;
- transition: all 0.2s ease;
-}
-
-.preview-img:hover {
- opacity: 1;
-}
-
-.stream-link a {
- /* color: inherit; */
- text-decoration: none;
- font-weight: 500;
-}
-
-.stream-link a:hover {
- text-decoration: underline;
-}