canvas签名

42 阅读1分钟

picture.png

<template>
  <div id="canvas-broad">
    <canvas id="canvas" :width="1200" :height="400" style="background-color: #ddd"></canvas>
    <hr />
    <el-button @click="exportCanvas">导出</el-button>
    <el-button @click="undo" :disabled="!canUndo">撤销</el-button>
    <el-button @click="redo" :disabled="!canRedo">重做</el-button>
    <el-button @click="reset">清空</el-button>
  </div>
</template>

<script>
export default {
  name: "JCanvasBroad",
  data() {
    return {
      isDown: false,
      lastX: 0,
      lastY: 0,
      canvas: null,
      ctx: null,

      points: [], // 当前笔画的点
      drawingHistory: [], // 所有笔画的历史记录
      historyIndex: -1 // 当前历史记录索引
    };
  },
  computed: {
    canUndo() {
      return this.historyIndex >= 0;
    },
    canRedo() {
      return this.historyIndex < this.drawingHistory.length - 1;
    }
  },
  mounted() {
    this.init();
    this.canvas.addEventListener("mousedown", this.mousedown, false);
    this.canvas.addEventListener("mousemove", this.mousemove, false);
    this.canvas.addEventListener("mouseup", this.mouseup, false);
    this.canvas.addEventListener("mouseout", this.mouseout, false);
  },
  methods: {
    init() {
      this.canvas = document.getElementById("canvas");
      this.ctx = this.canvas.getContext("2d");
      this.ctx.lineWidth = 5;
      this.ctx.lineJoin = "round";
      this.ctx.lineCap = "round";
      this.ctx.strokeStyle = "#000";
    },

    mousedown({ x, y }) {
      this.isDown = true;
      this.points = [{ x, y }]; // 开始新的笔画
      this.ctx.beginPath();
    },

    mousemove({ x, y }) {
      if (!this.isDown) return;

      const lastPoint = this.points[this.points.length - 1];
      this.draw(lastPoint.x, lastPoint.y, x, y);
      this.points.push({ x, y });
    },

    draw(startX, startY, endX, endY) {
      this.ctx.moveTo(startX, startY);
      this.ctx.lineTo(endX, endY);
      this.ctx.stroke();
    },

    mouseup() {
      if (this.isDown && this.points.length > 1) {
        this.saveStroke();
      }
      this.isDown = false;
    },

    mouseout() {
      if (this.isDown && this.points.length > 1) {
        this.saveStroke();
      }
      this.isDown = false;
    },

    saveStroke() {
      // 如果当前不是历史记录的最新状态,则丢弃后面的历史
      if (this.historyIndex < this.drawingHistory.length - 1) {
        this.drawingHistory = this.drawingHistory.slice(0, this.historyIndex + 1);
      }

      this.drawingHistory.push([...this.points]);
      this.historyIndex = this.drawingHistory.length - 1;
      this.points = [];
    },

    exportCanvas() {
      try {
        const img = this.canvas.toDataURL("image/png");
        const a = document.createElement("a");
        a.download = "picture.png";
        a.href = img;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      } catch (error) {
        console.error("导出图片时出错:", error);
      }
    },

    clearCanvas() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    },

    redraw() {
      this.clearCanvas();

      // 重绘所有历史记录,直到当前索引
      for (let i = 0; i <= this.historyIndex; i++) {
        const stroke = this.drawingHistory[i];
        if (stroke.length < 2) continue;

        this.ctx.beginPath();
        for (let j = 1; j < stroke.length; j++) {
          const prev = stroke[j - 1];
          const curr = stroke[j];
          this.draw(prev.x, prev.y, curr.x, curr.y);
        }
        this.ctx.closePath();
      }
    },

    undo() {
      if (this.canUndo) {
        this.historyIndex--;
        this.redraw();
      }
    },

    redo() {
      if (this.canRedo) {
        this.historyIndex++;
        this.redraw();
      }
    },

    reset() {
      this.clearCanvas();
      this.drawingHistory = [];
      this.historyIndex = -1;
      this.points = [];
    }
  }
};
</script>

<style lang="scss" scoped></style>