refactor(miaoImages): 将图片查看功能提取为独立组件
提取图片查看逻辑到独立的 MiaoImageViewer 组件,提高代码复用性和可维护性 移除原文件中的重复代码,统一处理图片缩放和拖拽功能
This commit is contained in:
1 parent
79221d37d6
commit
c1373de573
2 files changed
+138
-20
No files matched your search
@@ -0,0 +1,129 @@
|
|||||||
|
<template>
|
||||||
|
<miao-mask :show="show" @click="$emit('close')" class="miaoImage-mask" @wheel="handleWheel">
|
||||||
|
<ChevronBack class="miaoImage-mask-btn miaoImage-mask-btn-back" @click.stop="$emit('back')" />
|
||||||
|
<MiaoDraggableDiv
|
||||||
|
v-if="file"
|
||||||
|
:is-draggable="isDraggable"
|
||||||
|
:bind-virtual-files="[file]"
|
||||||
|
@dragend="handleDragEnd"
|
||||||
|
@pointerdown="handlePressStart"
|
||||||
|
@pointerup="handlePressEnd"
|
||||||
|
@pointercancel="handlePressEnd"
|
||||||
|
@pointerleave="handlePressEnd"
|
||||||
|
@touchstart.passive="handleTouchStart"
|
||||||
|
@touchend="handleTouchEnd"
|
||||||
|
>
|
||||||
|
<img :src="file.url" class="miaoImage-mask-active" @click="(e) => e.stopPropagation()" draggable="false" :style="{ transform: `scale(${imgViewScale})` }" />
|
||||||
|
</MiaoDraggableDiv>
|
||||||
|
<ChevronForward class="miaoImage-mask-btn miaoImage-mask-btn-forward" @click.stop="$emit('forward')" />
|
||||||
|
</miao-mask>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from 'vue'
|
||||||
|
import miaoMask from '@/components/miaoMask.vue'
|
||||||
|
import MiaoDraggableDiv from '@/components/miaoDraggableDiv.vue'
|
||||||
|
import { ChevronBack, ChevronForward } from '@vicons/ionicons5'
|
||||||
|
import type { VirtualFile } from '@/class/VirtualDirectory'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
show: boolean
|
||||||
|
file?: VirtualFile
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
close: []
|
||||||
|
back: []
|
||||||
|
forward: []
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const imgViewScale = ref(1)
|
||||||
|
const isDraggable = ref(false)
|
||||||
|
let pressTimer: number | undefined
|
||||||
|
|
||||||
|
const clearPress = () => {
|
||||||
|
if (pressTimer !== undefined) {
|
||||||
|
clearTimeout(pressTimer)
|
||||||
|
pressTimer = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePressStart = () => {
|
||||||
|
clearPress()
|
||||||
|
pressTimer = window.setTimeout(() => {
|
||||||
|
isDraggable.value = true
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePressEnd = () => {
|
||||||
|
clearPress()
|
||||||
|
// 延迟复位,避免影响 drop
|
||||||
|
setTimeout(() => {
|
||||||
|
isDraggable.value = false
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleTouchStart = () => handlePressStart()
|
||||||
|
const handleTouchEnd = () => handlePressEnd()
|
||||||
|
|
||||||
|
const handleDragEnd = () => {
|
||||||
|
isDraggable.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleWheel = (e: WheelEvent) => {
|
||||||
|
if (e.deltaY < 0) {
|
||||||
|
imgViewScale.value *= 1.42857
|
||||||
|
} else {
|
||||||
|
imgViewScale.value /= 1.42857
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.file,
|
||||||
|
() => {
|
||||||
|
imgViewScale.value = 1
|
||||||
|
isDraggable.value = false
|
||||||
|
clearPress()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.show,
|
||||||
|
(v) => {
|
||||||
|
if (!v) {
|
||||||
|
imgViewScale.value = 1
|
||||||
|
isDraggable.value = false
|
||||||
|
clearPress()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.miaoImage-mask {
|
||||||
|
background-color: rgba(0, 0, 0, 0.444);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miaoImage-mask-active {
|
||||||
|
max-width: 80%;
|
||||||
|
max-height: 80%;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miaoImage-mask-btn {
|
||||||
|
color: #ffffff99;
|
||||||
|
width: 7%;
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
|
&-back {
|
||||||
|
left: 1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-forward {
|
||||||
|
right: 1%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -25,28 +25,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</n-scrollbar>
|
</n-scrollbar>
|
||||||
<miao-mask :show="activeImage !== undefined" @click="activeImage = undefined" class="miaoImage-mask"
|
<MiaoImageViewer
|
||||||
@wheel="handleWheel">
|
:show="activeImage !== undefined"
|
||||||
<ChevronBack class="miaoImage-mask-btn miaoImage-mask-btn-back" @click="handleActiveImageBack" />
|
:file="activeImage"
|
||||||
<img :src="activeImage?.url" class="miaoImage-mask-active" @click="(e) => e.stopPropagation()"
|
@close="activeImage = undefined"
|
||||||
draggable="false" :style="{ transform: `scale(${imgViewScale})` }" />
|
@back="handleActiveImageBack"
|
||||||
<ChevronForward class="miaoImage-mask-btn miaoImage-mask-btn-forward"
|
@forward="handleActiveImageForward"
|
||||||
@click="handleActiveImageForward" />
|
/>
|
||||||
</miao-mask>
|
|
||||||
</div>
|
</div>
|
||||||
</miao-message-provider>
|
</miao-message-provider>
|
||||||
</miao-drop-handler>
|
</miao-drop-handler>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import miaoMask from '@/components/miaoMask.vue'
|
|
||||||
import miaoDropHandler from '@/components/miaoDropHandler.vue'
|
import miaoDropHandler from '@/components/miaoDropHandler.vue'
|
||||||
import miaoMessageProvider from '@/components/miaoAlertTipProvider.vue'
|
import miaoMessageProvider from '@/components/miaoAlertTipProvider.vue'
|
||||||
import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory'
|
import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory'
|
||||||
import uniq from 'lodash/uniq'
|
import uniq from 'lodash/uniq'
|
||||||
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
||||||
import { NScrollbar } from 'naive-ui'
|
import { NScrollbar } from 'naive-ui'
|
||||||
import { ChevronBack, ChevronForward } from '@vicons/ionicons5'
|
import MiaoImageViewer from './miaoImageViewer.vue'
|
||||||
|
|
||||||
const imageSuffixList = [
|
const imageSuffixList = [
|
||||||
'xbm',
|
'xbm',
|
||||||
@@ -80,7 +78,6 @@ const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
|
|||||||
const NScrollbarRef = ref()
|
const NScrollbarRef = ref()
|
||||||
const rootRef = ref<any>()
|
const rootRef = ref<any>()
|
||||||
const miaoMessageRef = ref<InstanceType<typeof miaoMessageProvider>>()
|
const miaoMessageRef = ref<InstanceType<typeof miaoMessageProvider>>()
|
||||||
const imgViewScale = ref(1)
|
|
||||||
const imageFileList = ref<VirtualFile[]>([])
|
const imageFileList = ref<VirtualFile[]>([])
|
||||||
const activeImage = ref<VirtualFile>()
|
const activeImage = ref<VirtualFile>()
|
||||||
|
|
||||||
@@ -90,7 +87,6 @@ const imageGroupList = computed(() => {
|
|||||||
|
|
||||||
watch(activeImage, () => {
|
watch(activeImage, () => {
|
||||||
nextTick(scrollToActiveImage)
|
nextTick(scrollToActiveImage)
|
||||||
imgViewScale.value = 1
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const groupByDay = (array: VirtualFile[]) => {
|
const groupByDay = (array: VirtualFile[]) => {
|
||||||
@@ -210,14 +206,6 @@ const updateImageSrcList = async (source: VirtualFile[] | VirtualDirectory) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleWheel = (e: WheelEvent) => {
|
|
||||||
if (e.deltaY < 0) {
|
|
||||||
imgViewScale.value *= 1.42857
|
|
||||||
} else {
|
|
||||||
imgViewScale.value /= 1.42857
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const length_before = imageFileList.value.length
|
const length_before = imageFileList.value.length
|
||||||
for (const i of [currentFiles.value, ...currentDirectories.value]) {
|
for (const i of [currentFiles.value, ...currentDirectories.value]) {
|
||||||
@@ -329,6 +317,7 @@ onMounted(async () => {
|
|||||||
width: 7%;
|
width: 7%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
&-back {
|
&-back {
|
||||||
left: 1%;
|
left: 1%;
|
||||||
|
|||||||
Reference in new issue
Block a user