import { LSignatureOptions, Point, Line } from '../../index.uts' let points : Line = [] let undoStack : Line[] = []; let redoStack : Line[] = []; let lastX = 0; let lastY = 0; export class Signature { el : UniElement options : LSignatureOptions = { penColor: 'black', openSmooth: true, disableScroll: true, disabled: false, penSize: 2, minLineWidth: 2, maxLineWidth: 6, minSpeed: 1.5, maxWidthDiffRate: 20, maxHistoryLength: 20 } as LSignatureOptions ctx : DrawableContext isEmpty : boolean = true isDrawing : boolean = false // historyList : Point[][] = [] // id : string // instance : ComponentPublicInstance constructor(el : UniElement) { this.el = el this.ctx = el.getDrawableContext() as DrawableContext this.init() } init() { this.el.addEventListener('touchstart', this.onTouchStart) this.el.addEventListener('touchmove', this.onTouchMove) this.el.addEventListener('touchend', this.onTouchEnd) } remove() { this.el.removeEventListener('touchstart', this.onTouchStart as UniCallbackWrapper) this.el.removeEventListener('touchmove', this.onTouchMove as UniCallbackWrapper) this.el.removeEventListener('touchend', this.onTouchEnd as UniCallbackWrapper) } setOption(options : LSignatureOptions) { this.options = options } disableScroll(event : UniTouchEvent) { event.stopPropagation() if (this.options.disableScroll) { { event.preventDefault() } } } getTouchPoint(event : UniTouchEvent) : Point { const rect = this.el.getBoundingClientRect() const touche = event.touches[0]; const x = touche.clientX const y = touche.clientY // const force = touche.force return { x: x - rect.left, y: y - rect.top } as Point } onTouchStart: (event : UniTouchEvent) => void = (event : UniTouchEvent) =>{ if (this.options.disabled) { return } this.disableScroll(event) const { x, y } = this.getTouchPoint(event) this.isDrawing = true; this.isEmpty = false lastX = x lastY = y points.push({ x, y } as Point); } onTouchMove: (event : UniTouchEvent) => void = (event : UniTouchEvent) =>{ if (this.options.disabled || !this.isDrawing) { return } this.disableScroll(event) const { x, y } = this.getTouchPoint(event) const lineWidth = this.options.penSize const strokeStyle = this.options.penColor const point = { x, y } as Point const last = { x: lastX, y: lastY } as Point this.drawLine(point, last, lineWidth, strokeStyle) lastX = x lastY = y points.push({ x, y, c: strokeStyle, w: lineWidth } as Point); } onTouchEnd: (event : UniTouchEvent) => void = (event : UniTouchEvent) =>{ this.disableScroll(event) this.isDrawing = false; undoStack.push(points); redoStack = [] as Line[]; points = [] as Point[]; } drawLine(point : Point, last : Point, lineWidth : number, strokeStyle : string) { const ctx = this.ctx ctx.lineWidth = lineWidth ctx.strokeStyle = strokeStyle ctx.lineCap = 'round' ctx.lineJoin = 'round' ctx.beginPath() ctx.moveTo(last.x, last.y) ctx.lineTo(point.x, point.y) ctx.stroke() ctx.update() } // addHistory() { } clear() { this.ctx.reset() this.ctx.update() this.isEmpty = true undoStack = [] as Line[]; redoStack = [] as Line[]; points = [] as Point[]; } undo() { if(redoStack.length == this.options.maxHistoryLength && this.options.maxHistoryLength != 0){ return } this.ctx.reset() if(undoStack.length > 0){ const lastPath : Line = undoStack.pop()!; redoStack.push(lastPath); if(undoStack.length == 0){ this.isEmpty = true this.ctx.update() return } for (let l = 0; l < undoStack.length; l++) { for (let i = 1; i < undoStack[l].length; i++) { const last = undoStack[l][i - 1] const point = undoStack[l][i] this.drawLine(point, last, point.w!, point.c!) } } } else { this.ctx.update() } } redo() { if(redoStack.length < 1) return const lastPath : Line = redoStack.pop()!; undoStack.push(lastPath); this.isEmpty = false for (let l = 0; l < undoStack.length; l++) { for (let i = 1; i < undoStack[l].length; i++) { const last = undoStack[l][i - 1] const point = undoStack[l][i] this.drawLine(point, last, point.w!, point.c!) } } } // restore() { } }