HomeLease/uni_modules/lime-signature/components/l-signature/signature.uts
2025-09-10 11:06:11 +08:00

213 lines
5.9 KiB
Plaintext

// @ts-nocheck
import { LimeSignatureOptions, LimeSignaturePoint, LimeSignatureLine } from '../../index.uts'
let points : LimeSignatureLine = []
let undoStack : LimeSignatureLine[] = [];
let redoStack : LimeSignatureLine[] = [];
let lastX = 0;
let lastY = 0;
// #ifdef APP-ANDROID || APP-IOS
type SignatureUniElement = UniElement
type SignatureCanvasContext = DrawableContext
// #endif
// #ifdef APP-HARMONY
type SignatureUniElement = UniCanvasElement
type SignatureCanvasContext = CanvasRenderingContext2D
// #endif
export class Signature {
el : SignatureUniElement
ctx : SignatureCanvasContext
options : LimeSignatureOptions = {
penColor: 'black',
openSmooth: true,
disableScroll: true,
disabled: false,
penSize: 2,
minLineWidth: 2,
maxLineWidth: 6,
minSpeed: 1.5,
maxWidthDiffRate: 20,
maxHistoryLength: 20
} as LimeSignatureOptions
isEmpty : boolean = true
isDrawing : boolean = false
// historyList : LimeSignaturePoint[][] = []
// id : string
// instance : ComponentPublicInstance
touchstartCallbackWrapper: UniCallbackWrapper|null = null
touchmoveCallbackWrapper: UniCallbackWrapper|null= null
touchendCallbackWrapper: UniCallbackWrapper|null= null
change: ((isEmpty: boolean) => void)|null = null
constructor(el : SignatureUniElement) {
this.el = el
// #ifdef APP-ANDROID || APP-IOS
this.ctx = el.getDrawableContext() as DrawableContext
// #endif
// #ifdef APP-HARMONY
const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
el.width = el.offsetWidth * dpr;
el.height = el.offsetHeight * dpr;
this.ctx = el.getContext('2d')
this.ctx.scale(dpr, dpr); // 仅需调用一次,当调用 reset 方法后需要再次 scale
// #endif
this.init()
}
onChange(cb: (isEmpty: boolean) => void){
this.change = cb
}
init() {
this.touchstartCallbackWrapper = this.el.addEventListener('touchstart', this.onTouchStart)
this.touchmoveCallbackWrapper = this.el.addEventListener('touchmove', this.onTouchMove)
this.touchendCallbackWrapper = this.el.addEventListener('touchend', this.onTouchEnd)
}
remove() {
if(this.touchstartCallbackWrapper == null) return
this.el.removeEventListener('touchstart', this.touchstartCallbackWrapper!)
this.el.removeEventListener('touchmove', this.touchmoveCallbackWrapper!)
this.el.removeEventListener('touchend', this.touchendCallbackWrapper!)
}
setOption(options : LimeSignatureOptions) {
this.options = options
}
disableScroll(event : UniTouchEvent) {
event.stopPropagation()
if (this.options.disableScroll) {
{
event.preventDefault()
}
}
}
getTouchLimeSignaturePoint(event : UniTouchEvent) : LimeSignaturePoint {
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 LimeSignaturePoint
}
onTouchStart: (event : UniTouchEvent) => void = (event : UniTouchEvent) =>{
if (this.options.disabled) {
return
}
this.disableScroll(event)
const { x, y } = this.getTouchLimeSignaturePoint(event)
this.isDrawing = true;
this.isEmpty = false
lastX = x
lastY = y
points.push({ x, y } as LimeSignaturePoint);
}
onTouchMove: (event : UniTouchEvent) => void = (event : UniTouchEvent) =>{
if (this.options.disabled || !this.isDrawing) {
return
}
this.disableScroll(event)
const { x, y } = this.getTouchLimeSignaturePoint(event)
const lineWidth = this.options.penSize
const strokeStyle = this.options.penColor
const point = { x, y } as LimeSignaturePoint
const last = { x: lastX, y: lastY } as LimeSignaturePoint
this.drawLine(point, last, lineWidth, strokeStyle)
lastX = x
lastY = y
points.push({ x, y, c: strokeStyle, w: lineWidth } as LimeSignaturePoint);
}
onTouchEnd: (event : UniTouchEvent) => void = (event : UniTouchEvent) =>{
this.disableScroll(event)
this.isDrawing = false;
undoStack.push(points);
redoStack = [] as LimeSignatureLine[];
points = [] as LimeSignaturePoint[];
this.change?.(this.isEmpty);
}
drawLine(point : LimeSignaturePoint, last : LimeSignaturePoint, 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.closePath()
// ctx.update()
this._draw()
}
_clear() {
// #ifdef APP-ANDROID || APP-IOS
this.ctx.reset()
// #endif
// #ifdef APP-HARMONY
this.ctx.clearRect(0,0,100000,100000)
// #endif
}
_draw() {
// #ifdef APP-ANDROID || APP-IOS
this.ctx.update()
// #endif
}
// addHistory() { }
clear() {
// this.ctx.reset()
// this.ctx.update()
this._clear()
this._draw()
this.isEmpty = true
undoStack = [] as LimeSignatureLine[];
redoStack = [] as LimeSignatureLine[];
points = [] as LimeSignaturePoint[];
}
undo() {
if(redoStack.length == this.options.maxHistoryLength && this.options.maxHistoryLength != 0){
return
}
// this.ctx.reset()
this._clear()
if(undoStack.length > 0){
const lastPath : LimeSignatureLine = undoStack.pop()!;
redoStack.push(lastPath);
if(undoStack.length == 0){
this.isEmpty = true
// this.ctx.update()
this._draw()
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()
this._draw()
}
}
redo() {
if(redoStack.length < 1) return
const lastPath : LimeSignatureLine = 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() { }
}