mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-12-16 00:39:40 +00:00
This commit is contained in:
parent
9057afb5ee
commit
6fd3317454
13 changed files with 427 additions and 47 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div ref="wrapper" :style="{ height: height + 'px', width: width + 'px' }" class="relative">
|
||||
<div ref="wrapper" :style="{ height: height + 'px', width: width + 'px' }" class="relative" @mouseover="mouseoverCover" @mouseleave="mouseleaveCover">
|
||||
<div v-if="noValidCovers" class="absolute top-0 left-0 w-full h-full flex items-center justify-center box-shadow-book" :style="{ padding: `${sizeMultiplier}rem` }">
|
||||
<p :style="{ fontSize: sizeMultiplier + 'rem' }">{{ name }}</p>
|
||||
</div>
|
||||
|
|
@ -15,17 +15,21 @@ export default {
|
|||
default: () => []
|
||||
},
|
||||
width: Number,
|
||||
height: Number
|
||||
height: Number,
|
||||
groupTo: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
noValidCovers: false,
|
||||
coverDiv: null,
|
||||
isHovering: false,
|
||||
coverWrapperEl: null,
|
||||
coverImageEls: [],
|
||||
coverWidth: 0,
|
||||
offsetIncrement: 0,
|
||||
isFannedOut: false
|
||||
isFannedOut: false,
|
||||
isDetached: false,
|
||||
isAttaching: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -42,14 +46,66 @@ export default {
|
|||
computed: {
|
||||
sizeMultiplier() {
|
||||
return this.width / 192
|
||||
},
|
||||
showExperimentalFeatures() {
|
||||
return this.$store.state.showExperimentalFeatures
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
mouseoverCover() {
|
||||
if (this.showExperimentalFeatures) this.setHover(true)
|
||||
},
|
||||
mouseleaveCover() {
|
||||
if (this.showExperimentalFeatures) this.setHover(false)
|
||||
},
|
||||
detchCoverWrapper() {
|
||||
if (!this.coverWrapperEl || !this.$refs.wrapper || this.isDetached) return
|
||||
|
||||
this.coverWrapperEl.remove()
|
||||
|
||||
this.isDetached = true
|
||||
document.body.appendChild(this.coverWrapperEl)
|
||||
this.coverWrapperEl.addEventListener('mouseleave', this.mouseleaveCover)
|
||||
|
||||
this.coverWrapperEl.style.position = 'absolute'
|
||||
this.coverWrapperEl.style.zIndex = 40
|
||||
|
||||
this.updatePosition()
|
||||
},
|
||||
attachCoverWrapper() {
|
||||
if (!this.coverWrapperEl || !this.$refs.wrapper || !this.isDetached) return
|
||||
|
||||
this.coverWrapperEl.remove()
|
||||
this.coverWrapperEl.style.position = 'relative'
|
||||
this.coverWrapperEl.style.left = 'unset'
|
||||
this.coverWrapperEl.style.top = 'unset'
|
||||
this.coverWrapperEl.style.width = this.$refs.wrapper.clientWidth + 'px'
|
||||
|
||||
this.$refs.wrapper.appendChild(this.coverWrapperEl)
|
||||
console.log('Appended to wrapper', this.$refs.wrapper.children)
|
||||
this.isDetached = false
|
||||
},
|
||||
updatePosition() {
|
||||
var rect = this.$refs.wrapper.getBoundingClientRect()
|
||||
this.coverWrapperEl.style.top = rect.top + window.scrollY + 'px'
|
||||
|
||||
this.coverWrapperEl.style.left = rect.left + window.scrollX + 4 + 'px'
|
||||
|
||||
this.coverWrapperEl.style.height = rect.height + 'px'
|
||||
this.coverWrapperEl.style.width = rect.width + 'px'
|
||||
},
|
||||
setHover(val) {
|
||||
if (this.isAttaching) return
|
||||
if (val && !this.isHovering) {
|
||||
this.detchCoverWrapper()
|
||||
this.fanOutCovers()
|
||||
} else if (!val && this.isHovering) {
|
||||
this.isAttaching = true
|
||||
this.reverseFan()
|
||||
setTimeout(() => {
|
||||
this.attachCoverWrapper()
|
||||
this.isAttaching = false
|
||||
}, 100)
|
||||
}
|
||||
this.isHovering = val
|
||||
},
|
||||
|
|
@ -57,15 +113,44 @@ export default {
|
|||
if (this.coverImageEls.length < 2 || this.isFannedOut) return
|
||||
this.isFannedOut = true
|
||||
var fanCoverWidth = this.coverWidth * 0.75
|
||||
var maximumWidth = window.innerWidth - 80
|
||||
|
||||
var totalFanWidth = (this.coverImageEls.length + 1) * fanCoverWidth
|
||||
|
||||
// If Fan width is too large, set new fan cover width
|
||||
if (totalFanWidth > maximumWidth) {
|
||||
fanCoverWidth = maximumWidth / (this.coverImageEls.length + 1)
|
||||
}
|
||||
|
||||
var fanWidth = (this.coverImageEls.length - 1) * fanCoverWidth
|
||||
var offsetLeft = (-1 * fanWidth) / 2
|
||||
|
||||
var rect = this.$refs.wrapper.getBoundingClientRect()
|
||||
|
||||
// If fan is going off page left or right, make adjustment
|
||||
var leftEdge = rect.left + offsetLeft
|
||||
var rightEdge = rect.left + rect.width - offsetLeft
|
||||
if (leftEdge < 0) {
|
||||
offsetLeft += leftEdge * -1
|
||||
}
|
||||
if (rightEdge + 80 > window.innerWidth) {
|
||||
var difference = rightEdge + 80 - window.innerWidth
|
||||
offsetLeft -= difference / 2
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.coverImageEls.length; i++) {
|
||||
var coverEl = this.coverImageEls[i]
|
||||
|
||||
// Series name card pop out further
|
||||
if (i === this.coverImageEls.length - 1) {
|
||||
offsetLeft += fanCoverWidth * 0.25
|
||||
}
|
||||
|
||||
coverEl.style.transform = `translateX(${offsetLeft}px)`
|
||||
offsetLeft += fanCoverWidth
|
||||
|
||||
var coverOverlay = document.createElement('div')
|
||||
coverOverlay.className = 'absolute top-0 left-0 w-full h-full hover:bg-black hover:bg-opacity-40 text-white text-opacity-0 hover:text-opacity-100 flex items-center justify-center'
|
||||
coverOverlay.className = 'absolute top-0 left-0 w-full h-full hover:bg-black hover:bg-opacity-40 text-white text-opacity-0 hover:text-opacity-100 flex items-center justify-center cursor-pointer'
|
||||
|
||||
if (coverEl.dataset.volumeNumber) {
|
||||
var pEl = document.createElement('p')
|
||||
|
|
@ -73,13 +158,22 @@ export default {
|
|||
pEl.textContent = `#${coverEl.dataset.volumeNumber}`
|
||||
coverOverlay.appendChild(pEl)
|
||||
}
|
||||
if (coverEl.dataset.audiobookId) {
|
||||
let audiobookId = coverEl.dataset.audiobookId
|
||||
coverOverlay.addEventListener('click', (e) => {
|
||||
this.$router.push(`/audiobook/${audiobookId}`)
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
} else {
|
||||
// Is Series
|
||||
coverOverlay.addEventListener('click', (e) => {
|
||||
this.$router.push(this.groupTo)
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
}
|
||||
|
||||
let audiobookId = coverEl.dataset.audiobookId
|
||||
coverOverlay.addEventListener('click', (e) => {
|
||||
this.$router.push(`/audiobook/${audiobookId}`)
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
})
|
||||
coverEl.appendChild(coverOverlay)
|
||||
}
|
||||
},
|
||||
|
|
@ -89,7 +183,7 @@ export default {
|
|||
for (let i = 0; i < this.coverImageEls.length; i++) {
|
||||
var coverEl = this.coverImageEls[i]
|
||||
coverEl.style.transform = 'translateX(0px)'
|
||||
if (coverEl.lastChild) coverEl.lastChild.remove()
|
||||
if (coverEl.lastChild) coverEl.lastChild.remove() // Remove cover overlay
|
||||
}
|
||||
},
|
||||
getCoverUrl(book) {
|
||||
|
|
@ -157,6 +251,22 @@ export default {
|
|||
imgdiv.appendChild(img)
|
||||
return imgdiv
|
||||
},
|
||||
createSeriesNameCover(offsetLeft) {
|
||||
var imgdiv = document.createElement('div')
|
||||
imgdiv.style.height = this.height + 'px'
|
||||
imgdiv.style.width = this.height / 1.6 + 'px'
|
||||
imgdiv.style.left = offsetLeft + 'px'
|
||||
imgdiv.className = 'absolute top-0 box-shadow-book transition-transform flex items-center justify-center'
|
||||
imgdiv.style.boxShadow = '4px 0px 4px #11111166'
|
||||
imgdiv.style.backgroundColor = '#111'
|
||||
|
||||
var innerP = document.createElement('p')
|
||||
innerP.textContent = this.name
|
||||
innerP.className = 'text-sm font-book text-white'
|
||||
imgdiv.appendChild(innerP)
|
||||
|
||||
return imgdiv
|
||||
},
|
||||
async init() {
|
||||
if (this.coverDiv) {
|
||||
this.coverDiv.remove()
|
||||
|
|
@ -187,16 +297,25 @@ export default {
|
|||
this.offsetIncrement = widthPer
|
||||
|
||||
var outerdiv = document.createElement('div')
|
||||
this.coverWrapperEl = outerdiv
|
||||
outerdiv.className = 'w-full h-full relative'
|
||||
|
||||
var coverImageEls = []
|
||||
var offsetLeft = 0
|
||||
for (let i = 0; i < validCovers.length; i++) {
|
||||
var offsetLeft = widthPer * i
|
||||
offsetLeft = widthPer * i
|
||||
var zIndex = validCovers.length - i
|
||||
var img = await this.buildCoverImg(validCovers[i], coverWidth, offsetLeft, zIndex, validCovers.length === 1)
|
||||
outerdiv.appendChild(img)
|
||||
coverImageEls.push(img)
|
||||
}
|
||||
|
||||
if (this.showExperimentalFeatures) {
|
||||
var seriesNameCover = this.createSeriesNameCover(offsetLeft)
|
||||
outerdiv.appendChild(seriesNameCover)
|
||||
coverImageEls.push(seriesNameCover)
|
||||
}
|
||||
|
||||
this.coverImageEls = coverImageEls
|
||||
|
||||
if (this.$refs.wrapper) {
|
||||
|
|
@ -205,6 +324,9 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
mounted() {}
|
||||
mounted() {},
|
||||
beforeDestroy() {
|
||||
if (this.coverWrapperEl) this.coverWrapperEl.remove()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Loading…
Add table
Add a link
Reference in a new issue