Skip to content

Commit

Permalink
add leave and enter event listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
UziTech committed Feb 25, 2023
1 parent 11272b4 commit a6f77c3
Showing 1 changed file with 156 additions and 44 deletions.
200 changes: 156 additions & 44 deletions src/signature_pad.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default class SignaturePad extends SignatureEventTarget {
// Private stuff
/* tslint:disable: variable-name */
private _ctx: CanvasRenderingContext2D;
private _drawningStroke = false;
private _drawingStroke = false;
private _isEmpty = true;
private _lastPoints: Point[] = []; // Stores up to 4 most recent points; used to generate a new curve
private _data: PointGroup[] = []; // Stores all points in groups (one group per line or dot)
Expand All @@ -76,7 +76,7 @@ export default class SignaturePad extends SignatureEventTarget {
this.velocityFilterWeight = options.velocityFilterWeight || 0.7;
this.minWidth = options.minWidth || 0.5;
this.maxWidth = options.maxWidth || 2.5;
this.throttle = ('throttle' in options ? options.throttle : 16) as number; // in milisecondss
this.throttle = ('throttle' in options ? options.throttle : 16) as number; // in milliseconds
this.minDistance = (
'minDistance' in options ? options.minDistance : 5
) as number; // in pixels
Expand Down Expand Up @@ -195,23 +195,30 @@ export default class SignaturePad extends SignatureEventTarget {
this.canvas.style.msTouchAction = 'auto';
this.canvas.style.userSelect = 'auto';

this.canvas.removeEventListener('pointerdown', this._handlePointerStart);
this.canvas.removeEventListener('pointerdown', this._handlePointerDown);
this.canvas.removeEventListener('pointermove', this._handlePointerMove);
this.canvas.removeEventListener('pointerleave', this._handlePointerLeave);
this.canvas.removeEventListener('pointerenter', this._handlePointerEnter);
this.canvas.ownerDocument.removeEventListener(
'pointerup',
this._handlePointerEnd,
this._handlePointerUp,
);
window.removeEventListener('pointerup', this._handlePointerUp);

this.canvas.removeEventListener('mousedown', this._handleMouseDown);
this.canvas.removeEventListener('mousemove', this._handleMouseMove);
this.canvas.removeEventListener('mouseleave', this._handleMouseLeave);
this.canvas.removeEventListener('mouseenter', this._handleMouseEnter);
this.canvas.ownerDocument.removeEventListener(
'mouseup',
this._handleMouseUp,
);
window.removeEventListener('mouseup', this._handleMouseUp);

this.canvas.removeEventListener('touchstart', this._handleTouchStart);
this.canvas.removeEventListener('touchmove', this._handleTouchMove);
this.canvas.removeEventListener('touchend', this._handleTouchEnd);
window.removeEventListener('touchend', this._handleTouchEnd);
}

public isEmpty(): boolean {
Expand Down Expand Up @@ -241,77 +248,159 @@ export default class SignaturePad extends SignatureEventTarget {

// Event handlers
private _handleMouseDown = (event: MouseEvent): void => {
if (event.buttons === 1) {
this._drawningStroke = true;
this._strokeBegin(event);
if (event.buttons !== 1 || this._drawingStroke) {
return;
}

this._drawingStroke = true;
this.canvas.addEventListener('mousemove', this._handleMouseMove);
this.canvas.addEventListener('mouseleave', this._handleMouseLeave);
this.canvas.addEventListener('mouseenter', this._handleMouseEnter);
this._strokeBegin(event);
};

private _handleMouseEnter = (event: MouseEvent): void => {
if (event.buttons !== 1 || this._drawingStroke) {
return;
}

this._drawingStroke = true;
this._strokeBegin(event);
};

private _handleMouseMove = (event: MouseEvent): void => {
if (this._drawningStroke) {
this._strokeMoveUpdate(event);
if (event.buttons !== 1 || !this._drawingStroke) {
// Stop when not pressing primary button or pressing multiple buttons
this._strokeEnd(event, false);
return;
}

this._strokeMoveUpdate(event);
};

private _handleMouseLeave = (event: MouseEvent): void => {
if (!this._drawingStroke) {
return;
}

this._drawingStroke = false;
this._strokeEnd(event, true, true);
};

private _handleMouseUp = (event: MouseEvent): void => {
if (event.buttons === 1 && this._drawningStroke) {
this._drawningStroke = false;
this._strokeEnd(event);
if (!this._drawingStroke) {
return;
}

this._strokeEnd(event);
};

private _handleTouchStart = (event: TouchEvent): void => {
if (this._drawingStroke) {
return;
}

const touch = event.targetTouches.item(0);
if (!touch) {
return;
}

// Prevent scrolling.
if (event.cancelable) {
event.preventDefault();
}

if (event.targetTouches.length === 1) {
const touch = event.changedTouches[0];
this._strokeBegin(touch);
}
this._drawingStroke = true;
this.canvas.addEventListener('touchmove', this._handleTouchMove);
this._strokeBegin(touch);
};

private _handleTouchMove = (event: TouchEvent): void => {
const touch = event.targetTouches.item(0);
if (!touch) {
return;
}

if (!this._drawingStroke) {
this._strokeEnd(touch, false);
return;
}

// Prevent scrolling.
if (event.cancelable) {
event.preventDefault();
}

const touch = event.targetTouches[0];
this._strokeMoveUpdate(touch);
};

private _handleTouchEnd = (event: TouchEvent): void => {
const wasCanvasTouched = event.target === this.canvas;
if (wasCanvasTouched) {
if (event.cancelable) {
event.preventDefault();
}
const touch = event.changedTouches[0];
this._strokeEnd(touch);
if (!this._drawingStroke) {
return;
}
const touch = event.changedTouches.item(0);
if (!touch) {
return;
}

if (event.cancelable) {
event.preventDefault();
}

this._strokeEnd(touch);
};

private _handlePointerDown = (event: PointerEvent): void => {
if (event.buttons !== 1 || this._drawingStroke) {
return;
}

event.preventDefault();
this._drawingStroke = true;
this.canvas.addEventListener('pointermove', this._handlePointerMove);
this.canvas.addEventListener('pointerenter', this._handlePointerEnter);
this.canvas.addEventListener('pointerleave', this._handlePointerLeave);
this._strokeBegin(event);
};

private _handlePointerStart = (event: PointerEvent): void => {
this._drawningStroke = true;
private _handlePointerEnter = (event: PointerEvent): void => {
if (event.buttons !== 1 || this._drawingStroke) {
return;
}

event.preventDefault();
this._drawingStroke = true;
this._strokeBegin(event);
};

private _handlePointerMove = (event: PointerEvent): void => {
if (this._drawningStroke) {
event.preventDefault();
this._strokeMoveUpdate(event);
if (event.buttons !== 1 || !this._drawingStroke) {
// Stop when primary button not pressed or multiple buttons pressed
this._strokeEnd(event, false);
return;
}

event.preventDefault();
this._strokeMoveUpdate(event);
};

private _handlePointerEnd = (event: PointerEvent): void => {
if (this._drawningStroke) {
event.preventDefault();
this._drawningStroke = false;
this._strokeEnd(event);
private _handlePointerLeave = (event: PointerEvent): void => {
if (!this._drawingStroke) {
return;
}

event.preventDefault();
this._drawingStroke = false;
this._strokeEnd(event, true, true);
};

private _handlePointerUp = (event: PointerEvent): void => {
if (!this._drawingStroke) {
return;
}

event.preventDefault();
this._strokeEnd(event);
};

private _getPointGroupOptions(group?: PointGroup) {
Expand Down Expand Up @@ -343,14 +432,18 @@ export default class SignaturePad extends SignatureEventTarget {
this._strokeUpdate(event);
}

private _strokeUpdate(event: SignatureEvent): void {
private _strokeUpdate(event: SignatureEvent, leaving = false): void {
if (this._data.length === 0) {
// This can happen if clear() was called while a signature is still in progress,
// or if there is a race condition between start/update events.
this._strokeBegin(event);
return;
}

if (leaving) {
console.log(event);
}

this.dispatchEvent(
new CustomEvent('beforeUpdateStroke', { detail: event }),
);
Expand Down Expand Up @@ -395,35 +488,54 @@ export default class SignaturePad extends SignatureEventTarget {
this.dispatchEvent(new CustomEvent('afterUpdateStroke', { detail: event }));
}

private _strokeEnd(event: SignatureEvent): void {
this._strokeUpdate(event);
private _strokeEnd(
event: SignatureEvent,
shouldUpdate = true,
leaving = false,
): void {
if (!leaving) {
this.canvas.removeEventListener('mousemove', this._handleMouseMove);
this.canvas.removeEventListener('mouseenter', this._handleMouseEnter);
this.canvas.removeEventListener('mouseleave', this._handleMouseLeave);
this.canvas.removeEventListener('touchmove', this._handleTouchMove);
this.canvas.removeEventListener('pointermove', this._handlePointerMove);
this.canvas.removeEventListener('pointerenter', this._handlePointerEnter);
this.canvas.removeEventListener('pointerleave', this._handlePointerLeave);
}
this._drawingStroke = false;
// touchend doesn't always have a type
if (shouldUpdate) {
this._strokeUpdate(event, leaving);
}

this.dispatchEvent(new CustomEvent('endStroke', { detail: event }));
}

private _handlePointerEvents(): void {
this._drawningStroke = false;
this._drawingStroke = false;

this.canvas.addEventListener('pointerdown', this._handlePointerStart);
this.canvas.addEventListener('pointermove', this._handlePointerMove);
this.canvas.addEventListener('pointerdown', this._handlePointerDown);
this.canvas.ownerDocument.addEventListener(
'pointerup',
this._handlePointerEnd,
this._handlePointerUp,
);
window.addEventListener('pointerup', this._handlePointerUp);
}

private _handleMouseEvents(): void {
this._drawningStroke = false;
this._drawingStroke = false;

this.canvas.addEventListener('mousedown', this._handleMouseDown);
this.canvas.addEventListener('mousemove', this._handleMouseMove);
this.canvas.ownerDocument.addEventListener('mouseup', this._handleMouseUp);
window.addEventListener('mouseup', this._handleMouseUp);
}

private _handleTouchEvents(): void {
this._drawingStroke = false;

this.canvas.addEventListener('touchstart', this._handleTouchStart);
this.canvas.addEventListener('touchmove', this._handleTouchMove);
this.canvas.addEventListener('touchend', this._handleTouchEnd);
window.addEventListener('touchend', this._handleTouchEnd);
}

// Called when a new line is started
Expand Down

0 comments on commit a6f77c3

Please sign in to comment.