index.vue 4.61 KB
<template>
  <div>
    <div class="tool-style">
      <el-button type="primary" size="mini" @click="reset">复位</el-button>
    </div>
    <div
      :style="{
        cursor: isDragging ? 'pointer' : 'default',
        top: canvasTop + 'px',
        left: canvasLeft + 'px',
      }"
      @wheel.prevent="onWheel"
      @mousedown="onMouseDown"
      @mousemove="onMouseMove"
      @mouseup="onMouseUp"
    >
      <canvas
        id="canvasId"
        width="1200"
        height="1000"
        style="border: 1px solid #000"
      ></canvas>
    </div>
  </div>
</template>

<script>
import { fabric } from "fabric";
export default {
  name: "DrawModule",
  data() {
    return {
      canvas: null,
      zoomLevel: 1, // 初始缩放比例
      isDragging: false, // 标记是否正在拖动
      lastPointer: null, // 记录上次鼠标位置
      canvasTop: 0, // 画布的顶部偏移
      canvasLeft: 0, // 画布的左部偏移
    };
  },
  props: {
    isActive: {
      type: Boolean,
      default: false,
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.canvas = new fabric.Canvas("canvasId");
      // 添加一个矩形
      const rect = new fabric.Rect({
        left: 100,
        top: 100,
        fill: "red",
        width: 50,
        height: 50,
        selectable: false, // 禁止拖动
      });
      const rect2 = new fabric.Rect({
        left: 300,
        top: 400,
        fill: "blue",
        width: 50,
        height: 50,
        selectable: false, // 禁止拖动
      });
      this.canvas.add(rect);
      this.canvas.add(rect2);
    });
  },
  methods: {
    reset() {
      this.zoomLevel = 1;
      this.canvas.setZoom(this.zoomLevel);
      this.canvasLeft = 0;
      this.canvasTop = 0;
    },

    onWheel(event) {
      // event.preventDefault(); // 阻止默认滚动行为

      // const delta = event.deltaY; // 获取滚轮滚动的距离
      // const zoomFactor = 0.1; // 缩放因子

      // if (delta > 0) {
      //   this.zoomLevel = Math.max(this.zoomLevel - zoomFactor, 0.1); // 缩小
      // } else {
      //   this.zoomLevel += zoomFactor; // 放大
      // }

      // this.canvas.setZoom(this.zoomLevel);
      // this.canvas.renderAll(); // 重新渲染画布

      event.preventDefault(); // 阻止默认滚动行为
      const delta = event.deltaY; // 获取滚轮滚动的距离
      const zoomFactor = 0.1; // 缩放因子
      const minZoom = 0.5; // 最小缩放比例
      const maxZoom = 5; // 最大缩放比例
      const oldZoom = this.zoomLevel;

      if (delta > 0) {
        this.zoomLevel = Math.max(this.zoomLevel - zoomFactor, minZoom); // 缩小
      } else {
        this.zoomLevel = Math.min(this.zoomLevel + zoomFactor, maxZoom); // 放大
      }

      const pointer = this.canvas.getPointer(event); // 获取鼠标指针位置

      // 只有当缩放级别发生变化时才进行缩放操作
      if (this.zoomLevel !== oldZoom) {
        const zoomRatio = this.zoomLevel / oldZoom;

        // 获取当前画布的视口变换矩阵
        const viewport = this.canvas.viewportTransform;

        // 计算缩放中心相对于画布左上角的偏移量
        const offsetX = pointer.x - viewport[4];
        const offsetY = pointer.y - viewport[5];

        // 缩放视口变换矩阵
        viewport[0] *= zoomRatio; // 缩放 X 轴
        viewport[3] *= zoomRatio; // 缩放 Y 轴

        // 调整视口变换矩阵的偏移量,以保持缩放中心不变
        viewport[4] = pointer.x - offsetX * zoomRatio;
        viewport[5] = pointer.y - offsetY * zoomRatio;

        // 更新画布的视口变换矩阵
        this.canvas.setViewportTransform(viewport);
      }

      this.canvas.renderAll(); // 重新渲染画布
    },

    onMouseDown(event) {
      this.isDragging = true;
      this.lastPointer = this.canvas.getPointer(event);
    },
    onMouseMove(event) {
      if (this.isDragging) {
        const currentPointer = this.canvas.getPointer(event);
        const deltaX = currentPointer.x - this.lastPointer.x;
        const deltaY = currentPointer.y - this.lastPointer.y;

        // 更新 canvasTop 和 canvasLeft
        this.canvasTop += deltaY;
        this.canvasLeft += deltaX;

        const viewport = this.canvas.viewportTransform;
        viewport[4] += deltaX;
        viewport[5] += deltaY;

        this.canvas.setViewportTransform(viewport);
        this.canvas.renderAll();

        this.lastPointer = currentPointer;
      }
    },
    onMouseUp() {
      this.isDragging = false;
    },
  },
};
</script>

<style scoped>
.tool-style {
  position: absolute;
  /* left: 0px;
  top: 0px; */
  margin: 10px;
  z-index: 99999;
}
</style>