安装
npm i fabric-with-erasing
html
<canvas #canvas style="position: absolute; top:0;left:0;z-index: 10;" id="main"></canvas>
<div class="right">
<button (click)="undo()">撤销</button>
<button (click)="redo()">恢复</button>
<button (click)="paint()">涂抹</button>
<button (click)="erase()">擦除</button>
<button (click)="save()">保存</button>
</div>
ts
import { Component, ElementRef, OnInit, Renderer2, ViewChild } from '@angular/core';
import 'fabric-with-erasing';
declare var fabric: any;
@Component({
selector: 'app-image-mark',
templateUrl: './image-mark.component.html',
styleUrls: ['./image-mark.component.less']
})
export class ImageMarkComponent implements OnInit {
canvas: any;
banner = ''
lastMousePosition: any;
ifErase = false
undoStack: any[] = [];
redoStack: any[] = [];
history: fabric.Object[] = [];
currentIndex: number = -1;
ctx: any;
constructor(private renderer: Renderer2) {
}
ngOnInit(): void {
this.createCanvas()
}
createCanvas() {
this.canvas = new fabric.Canvas('main', {
hoverCursor: 'pointer'
});
this.ctx = this.canvas.getContext('2d');
console.log(this.canvas)
// 设置画布显示比例
this.setPageStyle()
this.canvas.hoverCursor = 'none'
// 初始化画笔
const pencil = new fabric.PencilBrush(this.canvas);
// 设置画笔的样式
pencil.color = 'rgba(68,255,205,0.4)'; // 画笔颜色
pencil.width = 50; // 画笔宽度
// 将画笔绑定到 Canvas
this.canvas.freeDrawingBrush = pencil;
this.canvas.isDrawingMode = true; // 启用涂抹功能
this.saveHistory();
// 创建自定义鼠标样式对象
const customCursor = document.createElement('div');
customCursor.style.width = '50px';
customCursor.style.height = '50px';
customCursor.style.border = '3px solid #ffffff';
customCursor.style.background = 'rgba(255,255,255,0.6)'
customCursor.style.borderRadius = '50%';
customCursor.style.position = 'absolute';
customCursor.style.pointerEvents = 'none';
customCursor.style.display = 'none';
// 设置自定义鼠标样式
this.canvas.upperCanvasEl.style.cursor = 'none';
this.canvas.wrapperEl.appendChild(customCursor);
// 监听鼠标按下时事件,用于判断当前选中的元素,利用setInfo服务给全局发送当前编辑的对象。
this.canvas.on('mouse:up', (event: any) => {
console.log('鼠标抬起事件')
const snapshot = this.canvas.toJSON();
this.history.push(snapshot);
this.saveHistory();
})
this.canvas.on('mouse:down', (event: any) => {
console.log(event, 'down')
let pointer = this.canvas.getPointer(event.e);
});
this.canvas.on('mouse:move', (event: any) => {
this.canvas.upperCanvasEl.style.cursor = 'none';
const pointer = this.canvas.getPointer(event.e);
customCursor.style.left = pointer.x - 25 + 'px';
customCursor.style.top = pointer.y - 25 + 'px';
})
this.canvas.on('mouse:out', () => {
customCursor.style.display = 'none';
});
this.canvas.on('mouse:over', () => {
customCursor.style.display = 'block';
});
}
setPageStyle() {
this.canvas.setWidth(200)
this.canvas.setHeight(200);
this.canvas.backgroundColor = 'rgba(255, 255, 255, 0)';
this.canvas.renderAll();
}
//重做
clearCanvas() {
this.canvas.clear()
}
//保存
save() {
this.canvas.backgroundColor = 'white';
const base64Image = this.canvas.toDataURL('image/png', 1.0);
console.log(base64Image)
this.canvas.backgroundColor = 'rgba(255,255,255,0.1)'
// 创建一个下载链接
const link = document.createElement('a');
link.href = base64Image;
link.download = 'canvas_image.jpg';
// 触发下载
link.click();
}
//涂抹
paint() {
this.ifErase = false
const pencil = new fabric.PencilBrush(this.canvas);
// 设置画笔的样式
pencil.color = 'rgba(68,255,205,0.4)'; // 画笔颜色
pencil.width = 50; // 画笔宽度
// 将画笔绑定到 Canvas
this.canvas.freeDrawingBrush = pencil;
this.canvas.isDrawingMode = true;
}
//擦除
erase() {
// 启用橡皮擦功能
this.canvas.freeDrawingBrush = new fabric.EraserBrush(this.canvas);
// 自定义橡皮擦的宽度和颜色
this.canvas.freeDrawingBrush.width = 50; // 设置橡皮擦宽度
this.canvas.freeDrawingBrush.color = 'rgba(255, 255, 255, 1)'; // 设置橡皮擦颜色
}
saveHistory() {
const snapshot = this.canvas.toJSON();
this.history = this.history.slice(0, this.currentIndex + 1); // 截断未来的历史记录
this.history.push(snapshot);
this.currentIndex++;
}
undo() {
if (this.currentIndex > 0) {
this.currentIndex--;
this.loadHistory();
}
}
redo() {
if (this.currentIndex < this.history.length - 1) {
this.currentIndex++;
this.loadHistory();
}
}
loadHistory() {
const snapshot = this.history[this.currentIndex];
this.canvas.loadFromJSON(snapshot, () => {
this.canvas.renderAll();
});
}
}