设置点赞签名代码
export class Signature {width: number = 300height: number = 300canvas!: HTMLCanvasElementctx!: CanvasRenderingContext2Dprivate drawing: boolean = falsepreTask: string[] = []nextTask: string[] = []private allTask: { x: number; y: number; color: string }[][] = []private itemTask: { x: number; y: number; color: string }[] = []private lineWidth: number = 1private color: string = '#000'private background: string = '#ff234234'constructor(canvas: HTMLCanvasElement,width: number,height: number,lineWidth?: number,color?: string) {if (canvas instanceof HTMLCanvasElement != true) {console.warn('请传入一个Canvas元素')return}this.canvas = canvasthis.canvas.width = width || this.widththis.canvas.height = height || this.heightthis.lineWidth = lineWidth || this.lineWidththis.color = color || this.colorthis.ctx = canvas.getContext('2d') as CanvasRenderingContext2Dthis.eventListener()this.initCanvas()this.setColor()this.setLineWidth()}private initCanvas() {this.allTask = []this.preTask = []this.nextTask = []this.ctx.imageSmoothingEnabled = truethis.ctx.lineJoin = 'round' // 圆角连接this.ctx.lineCap = 'round' // 圆角线帽// this.ctx.translate(0.5, 0.5)this.ctx.strokeStyle = this.color}private eventListener() {this.canvas.addEventListener('mousedown', this.canvasMouseDown.bind(this))this.canvas.addEventListener('mousemove', this.canvasMouseMove.bind(this))this.canvas.addEventListener('mouseup', this.canvasMouseEnd.bind(this))this.canvas.addEventListener('mouseout', this.canvasMouseEnd.bind(this))}removeEventListener() {this.canvas.removeEventListener('mousedown',this.canvasMouseDown.bind(this))this.canvas.removeEventListener('mousemove',this.canvasMouseMove.bind(this))this.canvas.removeEventListener('mouseup', this.canvasMouseEnd.bind(this))this.canvas.removeEventListener('mouseout', this.canvasMouseEnd.bind(this))}private canvasMouseDown(e: MouseEvent) {this.drawing = truethis.ctx.beginPath() // 开始绘制this.ctx.moveTo(e.offsetX, e.offsetY) // 移动到this.itemTask.push({x: e.offsetX,y: e.offsetY,color: this.color,})}private canvasMouseMove(e: MouseEvent) {if (this.drawing) {this.ctx.lineTo(e.offsetX, e.offsetY) // 绘制到this.ctx.stroke() // 绘制this.itemTask.push({x: e.offsetX,y: e.offsetY,color: this.color,})}}private canvasMouseEnd(e: MouseEvent) {this.drawing = falsethis.ctx.closePath()const index = this.preTask.findIndex((item) => {return item === this.toDataURL()})if (index === -1) {this.preTask.push(this.toDataURL())}this.allTask.push(this.itemTask)this.itemTask = []}/*** @description: 设置画笔颜色* @param {string} color* @return {*}*/setColor(color?: string) {this.color = color || this.colorthis.ctx.strokeStyle = this.color}/*** @description: 设置画布背景* @param {string} background* @return {*}*/setBgColor(background?: string) {this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)this.background = background || this.backgroundthis.ctx.fillStyle = this.backgroundthis.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)this.allTask.length ? this.setPathLine() : ''}/*** @description: 设置折线* @return {*}*/private setPathLine() {const taskFilter = this.allTask.filter((item) => {return item.length})taskFilter.forEach((item) => {this.ctx.beginPath()this.ctx.moveTo(item[0].x, item[0].y)item.forEach((list, index) => {if (index) {this.ctx.lineTo(list.x, list.y)this.ctx.strokeStyle = list.colorthis.ctx.stroke()}})this.ctx.closePath()})}/*** @description: 设置线条宽度* @param {number} width* @return {*}*/setLineWidth(width?: number) {this.lineWidth = width || this.lineWidththis.ctx.lineWidth = this.lineWidth}/*** @description: 清空画布* @return {*}*/clear() {this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)this.preTask = []this.nextTask = []this.allTask = []}/*** @description: 上一个画布* @return {*}*/setPreImage() {if (this.preTask.length > 0) {const currentData = this.preTask.pop()!this.allTask.pop()!this.nextTask.push(currentData)const previousData = this.preTask[this.preTask.length - 1]if (previousData) {this.drawImage(previousData).then(() => console.log('撤销成功'))} else {this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)console.log('画布已清空')}console.log(`撤销: preTask = ${this.preTask.length}, nextTask = ${this.nextTask.length}`)}}/*** @description: 下一个画布* @return {*}*/setNextImage() {if (this.nextTask.length > 0) {const nextData = this.nextTask.pop()!this.preTask.push(nextData)this.drawImage(nextData).then(() => console.log('恢复成功'))console.log(`恢复: preTask = ${this.preTask.length}, nextTask = ${this.nextTask.length}`)}}/*** @description: 导入图片* @param {string} src* @return {*}*/drawImage(src: string,x = 0,y = 0,width = this.canvas.width,height = this.canvas.height) {return new Promise((resolve, reject) => {const image = new Image()image.onload = (e) => {this.ctx.clearRect(x, y, width, height)this.ctx.drawImage(image, x, y, width, height)resolve(e)}image.onerror = (e) => {reject(e)}image.src = src})}/*** @description: 转换成base64* @return {*}*/toDataURL(format: 'image/png' | 'image/jpeg' = 'image/png',quality: number = 1.0): string {return this.canvas.toDataURL(format, quality)}/*** @description: 导出图片* @return {*}*/exportToImage(fileName: string) {const url = this.canvas.toDataURL('image/png')var link = document.createElement('a')link.download = fileNamelink.href = urllink.click()}
}