vue消除笔实现
Vue 消除笔实现方案
核心思路
消除笔功能通常基于 Canvas 或 SVG 实现,通过记录用户绘制路径并与底层图像进行交互。Vue 作为框架主要负责状态管理和组件封装。
实现步骤
基础 Canvas 绘制
<template>
<canvas ref="canvas" @mousedown="startDrawing" @mousemove="draw" @mouseup="stopDrawing"/>
</template>
<script>
export default {
data() {
return {
isDrawing: false,
lastX: 0,
lastY: 0
}
},
methods: {
startDrawing(e) {
this.isDrawing = true;
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
},
draw(e) {
if (!this.isDrawing) return;
const ctx = this.$refs.canvas.getContext('2d');
ctx.globalCompositeOperation = 'destination-out'; // 关键消除模式
ctx.beginPath();
ctx.arc(e.offsetX, e.offsetY, 10, 0, Math.PI * 2);
ctx.fill();
},
stopDrawing() {
this.isDrawing = false;
}
}
}
</script>
进阶优化方案

-
路径平滑处理 使用贝塞尔曲线替代直线连接:
ctx.quadraticCurveTo( controlX, controlY, e.offsetX, e.offsetY ); -
压力感应支持 通过监听指针事件获取压力值:

window.PointerEvent && canvas.addEventListener('pointermove', (e) => { const pressure = e.pressure || 1; ctx.lineWidth = pressure * 20; }); -
撤销/重做功能 使用命令模式记录操作历史:
const history = []; const redoStack = [];
function saveState() { history.push(canvas.toDataURL()); }
4. 移动端适配
添加触摸事件支持:
```javascript
canvas.addEventListener('touchmove', (e) => {
e.preventDefault();
const touch = e.touches[0];
const mouseEvent = new MouseEvent('mousemove', {
clientX: touch.clientX,
clientY: touch.clientY
});
canvas.dispatchEvent(mouseEvent);
});
性能优化建议
- 使用
requestAnimationFrame节流绘制操作 - 对大型画布采用分层渲染策略
- 实现脏矩形算法减少重绘区域
- 考虑使用 OffscreenCanvas 进行后台处理
完整组件示例
<template>
<div class="eraser-container">
<canvas
ref="canvas"
:width="width"
:height="height"
@mousedown="startDrawing"
@mousemove="throttledDraw"
@mouseup="stopDrawing"
@touchstart="handleTouch"
@touchmove="handleTouch"
/>
<div class="controls">
<button @click="undo">撤销</button>
<input type="range" v-model="brushSize" min="1" max="50">
</div>
</div>
</template>
<script>
import { throttle } from 'lodash';
export default {
props: {
width: { type: Number, default: 800 },
height: { type: Number, default: 600 },
imageSrc: String
},
data() {
return {
brushSize: 10,
history: [],
redoStack: []
};
},
mounted() {
this.initCanvas();
this.throttledDraw = throttle(this.draw, 16);
},
methods: {
initCanvas() {
const ctx = this.$refs.canvas.getContext('2d');
if (this.imageSrc) {
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0, this.width, this.height);
this.saveState();
};
img.src = this.imageSrc;
}
}
}
};
</script>
注意事项
- 消除效果本质是通过
globalCompositeOperation设置混合模式 - 需要处理跨浏览器事件兼容性问题
- 高DPI设备需考虑像素比例适配
- 复杂场景建议使用 fabric.js 或 konva.js 等专业库






