
<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>