add rotate view to image viewer, mobile css fix

This commit is contained in:
Weidi Deng 2021-01-08 09:51:47 +08:00
parent 6e993dd095
commit fe9fedb14e
3 changed files with 85 additions and 10 deletions

View File

@ -0,0 +1,22 @@
<template>
<button :title="$t('buttons.info')" :aria-label="$t('buttons.info')" class="action" @click="$emit('rotate', rotate_left)">
<i class="material-icons">{{ this.icon }}</i>
<span>{{ $t('buttons.info') }}</span>
</button>
</template>
<script>
export default {
name: 'rotate-button',
props: [ 'rotate_left' ],
computed: {
icon () {
if (this.rotate_left) {
return 'rotate_left'
}
return 'rotate_right'
}
}
}
</script>

View File

@ -20,6 +20,7 @@ import throttle from 'lodash.throttle'
export default {
props: {
src: String,
angle: Number,
moveDisabledTime: {
type: Number,
default: () => 200
@ -83,17 +84,35 @@ export default {
watch: {
src: function () {
this.setCenter()
},
angle: function () {
this.setCenter()
}
},
computed: {
imgHeight() {
let img = this.$refs.imgex
// slow version
// return img.clientHeight * Math.cos(this.angle * Math.PI) + img.clientWidth * Math.sin(this.angle * Math.PI)
return !(this.angle % 180) ? img.clientHeight : img.clientWidth
},
imgWidth() {
let img = this.$refs.imgex
// slow version
// return img.clientWidth * Math.cos(this.angle * Math.PI) + img.clientHeight * Math.sin(this.angle * Math.PI)
return !(this.angle % 180) ? img.clientWidth : img.clientHeight
}
},
methods: {
fit() {
let img = this.$refs.imgex
const wScale = window.innerWidth / img.clientWidth
const hScale = window.innerHeight / img.clientHeight
const wScale = window.innerWidth / this.imgWidth
const hScale = window.innerHeight / this.imgHeight
this.scale = Math.min(wScale, hScale)
this.minScale = this.scale
this.maxScale = 4 * this.scale
this.setZoom()
},
refit() {
@ -288,7 +307,7 @@ export default {
setZoom() {
this.scale = this.scale < this.minScale ? this.minScale : this.scale
this.scale = this.scale > this.maxScale ? this.maxScale : this.scale
this.$refs.imgex.style.transform = `scale(${this.scale})`
this.$refs.imgex.style.transform = `scale(${this.scale}) rotate(${this.angle}deg)`
this.refit()
},
pxStringToNumber(style) {

View File

@ -7,7 +7,9 @@
<div class="title">{{ this.name }}</div>
<preview-size-button v-if="isResizeEnabled && req.type === 'image'" @change-size="toggleSize" v-bind:size="fullSize" :disabled="loading"></preview-size-button>
<rotate-button v-if="isGallery" :rotate_left="true" @rotate="setRotate($event)" :disabled="loading"></rotate-button>
<rotate-button v-if="isGallery" :rotate_left="false" @rotate="setRotate($event)" :disabled="loading"></rotate-button>
<preview-size-button v-if="isResizeEnabled && isGallery" @change-size="toggleSize" v-bind:size="fullSize" :disabled="loading"></preview-size-button>
<button @click="openMore" id="more" :aria-label="$t('buttons.more')" :title="$t('buttons.more')" class="action">
<i class="material-icons">more_vert</i>
</button>
@ -37,7 +39,7 @@
<template v-if="!loading">
<div class="preview">
<ExtendedImage v-if="isGallery" :src="raw"></ExtendedImage>
<ExtendedImage v-if="isGallery" :src="raw" :angle="angle"></ExtendedImage>
<audio v-else-if="req.type == 'audio'" :src="raw" autoplay controls></audio>
<video v-else-if="req.type == 'video'" :src="raw" autoplay controls>
<track
@ -66,6 +68,7 @@ import { mapState } from 'vuex'
import url from '@/utils/url'
import { baseURL, resizePreview } from '@/utils/constants'
import { files as api } from '@/api'
import RotateButton from "@/components/buttons/RotatePreview"
import PreviewSizeButton from '@/components/buttons/PreviewSize'
import InfoButton from '@/components/buttons/Info'
import DeleteButton from '@/components/buttons/Delete'
@ -82,6 +85,7 @@ const mediaTypes = [
export default {
name: 'preview',
components: {
RotateButton,
PreviewSizeButton,
InfoButton,
DeleteButton,
@ -97,7 +101,8 @@ export default {
name: '',
subtitles: [],
fullSize: false,
isGallery: false
isGallery: false,
angle: 0
}
},
computed: {
@ -130,6 +135,9 @@ export default {
watch: {
$route: function () {
this.updatePreview()
},
showMore: function () {
if (!this.showMore) this.hideGalleryBar()
}
},
created() {
@ -140,20 +148,38 @@ export default {
this.$store.commit('setPreviewMode', true)
this.listing = this.oldReq.items
this.$root.$on('preview-deleted', this.deleted)
if (this.isGallery) this.$root.$on('gallery-nav', this.nav)
if (this.isGallery) {
this.$root.$on('gallery-nav', this.nav)
document.querySelector('#previewer .overlay').addEventListener('mouseenter', this.showGalleryBar)
document.querySelector('#previewer .gallery-bar #dropdown').addEventListener('mouseenter', this.showGalleryBar)
}
this.updatePreview()
},
beforeDestroy () {
window.removeEventListener('keydown', this.key)
this.$store.commit('setPreviewMode', false)
this.$root.$off('preview-deleted', this.deleted)
if (this.isGallery) this.$root.$off('gallery-nav', this.nav)
if (this.isGallery) {
this.$root.$off('gallery-nav', this.nav)
document.querySelector('#previewer .overlay').removeEventListener('mouseenter', this.showGalleryBar)
document.querySelector('#previewer .gallery-bar #dropdown').removeEventListener('mouseenter', this.showGalleryBar)
}
},
methods: {
nav(e) {
if (e===0 && this.hasPrevious) this.prev()
else if (e===1 && this.hasNext) this.next()
},
showGalleryBar() {
document.querySelector('#previewer .gallery-bar').style.opacity = 1
document.querySelector('#previewer .gallery-bar').style.zIndex = 'auto'
document.querySelector('#previewer .preview .image-ex-container').style.zIndex = -1
},
hideGalleryBar() {
document.querySelector('#previewer .gallery-bar').style.removeProperty('opacity')
document.querySelector('#previewer .gallery-bar').style.zIndex = 2
document.querySelector('#previewer .preview .image-ex-container').style.zIndex = 'auto'
},
deleted () {
this.listing = this.listing.filter(item => item.name !== this.name)
@ -189,6 +215,7 @@ export default {
}
},
async updatePreview () {
this.angle = 0
if (this.req.subtitles) {
this.subtitles = this.req.subtitles.map(sub => `${baseURL}/api/raw${sub}?auth=${this.jwt}&inline=true`)
}
@ -243,6 +270,13 @@ export default {
resetPrompts () {
this.$store.commit('closeHovers')
},
setRotate(rotate_left) {
if (rotate_left) {
this.angle -= 90
} else {
this.angle += 90
}
},
toggleSize () {
this.fullSize = !this.fullSize
}