| | |
| | | <img |
| | | :src="currentFile.previewUrl" |
| | | class="file-preview__image" |
| | | :style="{ |
| | | transform: |
| | | 'scale(' + imageScale + ') rotate(' + imageRotate + 'deg)' |
| | | }" |
| | | :class="{ 'is-dragging': imageDragging }" |
| | | :style="imageStyle" |
| | | draggable="false" |
| | | alt="图片预览" |
| | | @mousedown="startImageDrag" |
| | | @click="toggleImageZoom" |
| | | @dragstart.prevent |
| | | /> |
| | | </div> |
| | | </div> |
| | |
| | | currentIndex: 0, |
| | | imageScale: 1, |
| | | imageRotate: 0, |
| | | imageOffsetX: 0, |
| | | imageOffsetY: 0, |
| | | imageDragging: false, |
| | | imageDragMoved: false, |
| | | imageDragStartX: 0, |
| | | imageDragStartY: 0, |
| | | imageDragOriginX: 0, |
| | | imageDragOriginY: 0, |
| | | fullscreen: false |
| | | }; |
| | | }, |
| | | computed: { |
| | | currentFile() { |
| | | return this.previewFiles[this.currentIndex] || null; |
| | | }, |
| | | imageStyle() { |
| | | return { |
| | | transform: |
| | | "translate(" + |
| | | this.imageOffsetX + |
| | | "px," + |
| | | this.imageOffsetY + |
| | | "px) scale(" + |
| | | this.imageScale + |
| | | ") rotate(" + |
| | | this.imageRotate + |
| | | "deg)" |
| | | }; |
| | | } |
| | | }, |
| | | methods: { |
| | |
| | | resetImage() { |
| | | this.imageScale = 1; |
| | | this.imageRotate = 0; |
| | | this.imageOffsetX = 0; |
| | | this.imageOffsetY = 0; |
| | | }, |
| | | startImageDrag(e) { |
| | | if (e.button !== 0) return; |
| | | this.imageDragging = true; |
| | | this.imageDragMoved = false; |
| | | this.imageDragStartX = e.clientX; |
| | | this.imageDragStartY = e.clientY; |
| | | this.imageDragOriginX = this.imageOffsetX; |
| | | this.imageDragOriginY = this.imageOffsetY; |
| | | document.addEventListener("mousemove", this.onImageDrag); |
| | | document.addEventListener("mouseup", this.endImageDrag); |
| | | }, |
| | | onImageDrag(e) { |
| | | if (!this.imageDragging) return; |
| | | const dx = e.clientX - this.imageDragStartX; |
| | | const dy = e.clientY - this.imageDragStartY; |
| | | if (Math.abs(dx) > 3 || Math.abs(dy) > 3) { |
| | | this.imageDragMoved = true; |
| | | } |
| | | this.imageOffsetX = this.imageDragOriginX + dx; |
| | | this.imageOffsetY = this.imageDragOriginY + dy; |
| | | }, |
| | | endImageDrag() { |
| | | this.imageDragging = false; |
| | | document.removeEventListener("mousemove", this.onImageDrag); |
| | | document.removeEventListener("mouseup", this.endImageDrag); |
| | | }, |
| | | toggleImageZoom() { |
| | | if (this.imageDragMoved) { |
| | | this.imageDragMoved = false; |
| | | return; |
| | | } |
| | | this.imageScale = this.imageScale === 1 ? 1.5 : 1; |
| | | }, |
| | | handleDownload() { |
| | | const file = this.currentFile; |
| | |
| | | } |
| | | }, |
| | | handleClosed() { |
| | | this.endImageDrag(); |
| | | this.revokeUrls(); |
| | | this.previewFiles = []; |
| | | this.fileList = []; |
| | |
| | | } |
| | | }, |
| | | beforeDestroy() { |
| | | this.endImageDrag(); |
| | | this.revokeUrls(); |
| | | } |
| | | }; |
| | |
| | | max-height: 100%; |
| | | transition: transform 0.2s ease; |
| | | transform-origin: center center; |
| | | cursor: grab; |
| | | user-select: none; |
| | | } |
| | | .file-preview__image.is-dragging { |
| | | cursor: grabbing; |
| | | transition: none; |
| | | } |
| | | .file-preview__image-pane { |
| | | width: 100%; |