yxh
6 天以前 e1dd822239ce5b1fd85462c95b264b300153a4cf
src/components/FilePreview/index.vue
@@ -92,11 +92,13 @@
              <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>
@@ -158,12 +160,34 @@
      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: {
@@ -334,6 +358,41 @@
    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;
@@ -357,6 +416,7 @@
      }
    },
    handleClosed() {
      this.endImageDrag();
      this.revokeUrls();
      this.previewFiles = [];
      this.fileList = [];
@@ -373,6 +433,7 @@
    }
  },
  beforeDestroy() {
    this.endImageDrag();
    this.revokeUrls();
  }
};
@@ -430,6 +491,12 @@
  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%;