mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Cover image aspect ratio solution
This commit is contained in:
		
							parent
							
								
									c208e876d2
								
							
						
					
					
						commit
						091aa6ef82
					
				| @ -1,6 +1,9 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="relative rounded-sm overflow-hidden" :style="{ height: width * 1.6 + 'px', width: width + 'px', maxWidth: width + 'px', minWidth: width + 'px' }"> |   <div class="relative rounded-sm overflow-hidden" :style="{ height: width * 1.6 + 'px', width: width + 'px', maxWidth: width + 'px', minWidth: width + 'px' }"> | ||||||
|     <img ref="cover" :src="cover" @error="imageError" class="w-full h-full object-cover" /> |     <div class="w-full h-full bg-bg relative"> | ||||||
|  |       <div v-if="showCoverBg" class="absolute top-0 left-0 w-full h-full z-0" ref="coverBg" /> | ||||||
|  |       <img ref="cover" :src="cover" @error="imageError" @load="imageLoaded" class="w-full h-full absolute top-0 left-0" :class="showCoverBg ? 'object-contain' : 'object-cover'" /> | ||||||
|  |     </div> | ||||||
| 
 | 
 | ||||||
|     <div v-if="imageFailed" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full bg-red-100" :style="{ padding: placeholderCoverPadding + 'rem' }"> |     <div v-if="imageFailed" class="absolute top-0 left-0 right-0 bottom-0 w-full h-full bg-red-100" :style="{ padding: placeholderCoverPadding + 'rem' }"> | ||||||
|       <div class="w-full h-full border-2 border-error flex flex-col items-center justify-center"> |       <div class="w-full h-full border-2 border-error flex flex-col items-center justify-center"> | ||||||
| @ -21,6 +24,8 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script> | <script> | ||||||
|  | import Path from 'path' | ||||||
|  | 
 | ||||||
| export default { | export default { | ||||||
|   props: { |   props: { | ||||||
|     audiobook: { |     audiobook: { | ||||||
| @ -35,7 +40,8 @@ export default { | |||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       imageFailed: false |       imageFailed: false, | ||||||
|  |       showCoverBg: false | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   watch: { |   watch: { | ||||||
| @ -66,8 +72,23 @@ export default { | |||||||
|       } |       } | ||||||
|       return this.author |       return this.author | ||||||
|     }, |     }, | ||||||
|  |     placeholderUrl() { | ||||||
|  |       return '/book_placeholder.jpg' | ||||||
|  |     }, | ||||||
|  |     fullCoverUrl() { | ||||||
|  |       if (!this.cover || this.cover === this.placeholderUrl) return '' | ||||||
|  |       if (this.cover.startsWith('http:') || this.cover.startsWith('https:')) return this.cover | ||||||
|  |       try { | ||||||
|  |         var url = new URL(this.cover, document.baseURI) | ||||||
|  |         return url.href | ||||||
|  |       } catch (err) { | ||||||
|  |         console.error(err) | ||||||
|  |         return '' | ||||||
|  |       } | ||||||
|  |       return `${process.env.serverUrl}/${Path.normalize(this.cover)}` | ||||||
|  |     }, | ||||||
|     cover() { |     cover() { | ||||||
|       return this.book.cover || '/book_placeholder.jpg' |       return this.book.cover || this.placeholderUrl | ||||||
|     }, |     }, | ||||||
|     hasCover() { |     hasCover() { | ||||||
|       return !!this.book.cover |       return !!this.book.cover | ||||||
| @ -89,6 +110,31 @@ export default { | |||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|  |     setCoverBg() { | ||||||
|  |       if (this.$refs.coverBg) { | ||||||
|  |         this.$refs.coverBg.style.backgroundImage = `url("${this.fullCoverUrl}")` | ||||||
|  |         this.$refs.coverBg.style.backgroundSize = 'cover' | ||||||
|  |         this.$refs.coverBg.style.backgroundPosition = 'center' | ||||||
|  |         this.$refs.coverBg.style.opacity = 0.25 | ||||||
|  |         this.$refs.coverBg.style.filter = 'blur(1px)' | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     hideCoverBg() {}, | ||||||
|  |     imageLoaded() { | ||||||
|  |       if (this.$refs.cover && this.cover !== this.placeholderUrl) { | ||||||
|  |         var { naturalWidth, naturalHeight } = this.$refs.cover | ||||||
|  |         var aspectRatio = naturalHeight / naturalWidth | ||||||
|  |         var arDiff = Math.abs(aspectRatio - 1.6) | ||||||
|  | 
 | ||||||
|  |         // If image aspect ratio is <= 1.45 or >= 1.75 then use cover bg, otherwise stretch to fit | ||||||
|  |         if (arDiff > 0.15) { | ||||||
|  |           this.showCoverBg = true | ||||||
|  |           this.$nextTick(this.setCoverBg) | ||||||
|  |         } else { | ||||||
|  |           this.showCoverBg = false | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     imageError(err) { |     imageError(err) { | ||||||
|       console.error('ImgError', err) |       console.error('ImgError', err) | ||||||
|       this.imageFailed = true |       this.imageFailed = true | ||||||
|  | |||||||
| @ -29,7 +29,9 @@ | |||||||
|           <div v-if="showLocalCovers" class="flex items-center justify-center"> |           <div v-if="showLocalCovers" class="flex items-center justify-center"> | ||||||
|             <template v-for="cover in localCovers"> |             <template v-for="cover in localCovers"> | ||||||
|               <div :key="cover.path" class="m-0.5 border-2 border-transparent hover:border-yellow-300 cursor-pointer" :class="cover.localPath === imageUrl ? 'border-yellow-300' : ''" @click="setCover(cover.localPath)"> |               <div :key="cover.path" class="m-0.5 border-2 border-transparent hover:border-yellow-300 cursor-pointer" :class="cover.localPath === imageUrl ? 'border-yellow-300' : ''" @click="setCover(cover.localPath)"> | ||||||
|                 <img :src="cover.localPath" class="h-24 object-cover" style="width: 60px" /> |                 <div class="h-24 bg-primary" style="width: 60px"> | ||||||
|  |                   <img :src="cover.localPath" class="h-full w-full object-contain" /> | ||||||
|  |                 </div> | ||||||
|               </div> |               </div> | ||||||
|             </template> |             </template> | ||||||
|           </div> |           </div> | ||||||
| @ -52,7 +54,10 @@ | |||||||
|           <p v-if="!coversFound.length">No Covers Found</p> |           <p v-if="!coversFound.length">No Covers Found</p> | ||||||
|           <template v-for="cover in coversFound"> |           <template v-for="cover in coversFound"> | ||||||
|             <div :key="cover" class="m-0.5 border-2 border-transparent hover:border-yellow-300 cursor-pointer" :class="cover === imageUrl ? 'border-yellow-300' : ''" @click="setCover(cover)"> |             <div :key="cover" class="m-0.5 border-2 border-transparent hover:border-yellow-300 cursor-pointer" :class="cover === imageUrl ? 'border-yellow-300' : ''" @click="setCover(cover)"> | ||||||
|               <img :src="cover" class="h-24 object-cover" style="width: 60px" /> |               <div class="h-24 bg-primary" style="width: 60px"> | ||||||
|  |                 <img :src="cover" class="h-full w-full object-contain" /> | ||||||
|  |               </div> | ||||||
|  |               <!-- <img :src="cover" class="h-24 object-cover" style="width: 60px" /> --> | ||||||
|             </div> |             </div> | ||||||
|           </template> |           </template> | ||||||
|         </div> |         </div> | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "audiobookshelf-client", |   "name": "audiobookshelf-client", | ||||||
|   "version": "0.9.79-beta", |   "version": "0.9.80-beta", | ||||||
|   "description": "Audiobook manager and player", |   "description": "Audiobook manager and player", | ||||||
|   "main": "index.js", |   "main": "index.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "audiobookshelf", |   "name": "audiobookshelf", | ||||||
|   "version": "0.9.79-beta", |   "version": "0.9.80-beta", | ||||||
|   "description": "Self-hosted audiobook server for managing and playing audiobooks.", |   "description": "Self-hosted audiobook server for managing and playing audiobooks.", | ||||||
|   "main": "index.js", |   "main": "index.js", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user