diff --git a/README.md b/README.md
index ed4253d0..7e115412 100644
--- a/README.md
+++ b/README.md
@@ -130,7 +130,7 @@ signaturePad.penColor = "rgb(66, 133, 244)";
- beginStroke
-- Triggered before stroke begins.
+- Triggered before stroke begins.
Can be canceled with event.preventDefault()
- endStroke
- Triggered after stroke ends.
- beforeUpdateStroke
diff --git a/src/signature_pad.ts b/src/signature_pad.ts
index e4fd17a7..7aacfefa 100644
--- a/src/signature_pad.ts
+++ b/src/signature_pad.ts
@@ -69,7 +69,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)
@@ -250,20 +250,16 @@ export default class SignaturePad extends SignatureEventTarget {
// Event handlers
private _handleMouseDown = (event: MouseEvent): void => {
if (event.buttons === 1) {
- this._drawningStroke = true;
this._strokeBegin(event);
}
};
private _handleMouseMove = (event: MouseEvent): void => {
- if (this._drawningStroke) {
- this._strokeMoveUpdate(event);
- }
+ this._strokeMoveUpdate(event);
};
private _handleMouseUp = (event: MouseEvent): void => {
- if (event.buttons === 1 && this._drawningStroke) {
- this._drawningStroke = false;
+ if (event.buttons === 1) {
this._strokeEnd(event);
}
};
@@ -302,22 +298,17 @@ export default class SignaturePad extends SignatureEventTarget {
};
private _handlePointerStart = (event: PointerEvent): void => {
- this._drawningStroke = true;
event.preventDefault();
this._strokeBegin(event);
};
private _handlePointerMove = (event: PointerEvent): void => {
- if (this._drawningStroke) {
- event.preventDefault();
- this._strokeMoveUpdate(event);
- }
+ this._strokeMoveUpdate(event);
};
private _handlePointerEnd = (event: PointerEvent): void => {
- if (this._drawningStroke) {
+ if (this._drawingStroke) {
event.preventDefault();
- this._drawningStroke = false;
this._strokeEnd(event);
}
};
@@ -341,7 +332,13 @@ export default class SignaturePad extends SignatureEventTarget {
// Private methods
private _strokeBegin(event: SignatureEvent): void {
- this.dispatchEvent(new CustomEvent('beginStroke', { detail: event }));
+ const cancelled = !this.dispatchEvent(
+ new CustomEvent('beginStroke', { detail: event, cancelable: true }),
+ );
+ if (cancelled) {
+ return;
+ }
+ this._drawingStroke = true;
const pointGroupOptions = this._getPointGroupOptions();
@@ -356,6 +353,10 @@ export default class SignaturePad extends SignatureEventTarget {
}
private _strokeUpdate(event: SignatureEvent): void {
+ if (!this._drawingStroke) {
+ return;
+ }
+
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.
@@ -373,8 +374,8 @@ export default class SignaturePad extends SignatureEventTarget {
(event as PointerEvent).pressure !== undefined
? (event as PointerEvent).pressure
: (event as Touch).force !== undefined
- ? (event as Touch).force
- : 0;
+ ? (event as Touch).force
+ : 0;
const point = this._createPoint(x, y, pressure);
const lastPointGroup = this._data[this._data.length - 1];
@@ -408,13 +409,18 @@ export default class SignaturePad extends SignatureEventTarget {
}
private _strokeEnd(event: SignatureEvent): void {
+ if (!this._drawingStroke) {
+ return;
+ }
+
this._strokeUpdate(event);
+ this._drawingStroke = false;
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);
@@ -425,7 +431,7 @@ export default class SignaturePad extends SignatureEventTarget {
}
private _handleMouseEvents(): void {
- this._drawningStroke = false;
+ this._drawingStroke = false;
this.canvas.addEventListener('mousedown', this._handleMouseDown);
this.canvas.addEventListener('mousemove', this._handleMouseMove);
diff --git a/tests/signature_pad.test.ts b/tests/signature_pad.test.ts
index 521046cb..386b01e7 100644
--- a/tests/signature_pad.test.ts
+++ b/tests/signature_pad.test.ts
@@ -67,7 +67,7 @@ describe('#clear', () => {
const context = canvas.getContext('2d') as CanvasRenderingContext2D;
expect(context.globalCompositeOperation).toBe('destination-out');
- })
+ });
});
describe('#isEmpty', () => {
@@ -141,9 +141,7 @@ describe('#toDataURL', () => {
const pad = new SignaturePad(canvas);
pad.fromData(face);
- expect(pad.toDataURL()).toEqual(
- expect.stringMatching('data:image/png'),
- );
+ expect(pad.toDataURL()).toEqual(expect.stringMatching('data:image/png'));
});
it('returns PNG image in data URL format', () => {
@@ -491,4 +489,43 @@ describe('Signature events.', () => {
expect(event.detail).toBe(pointerEvent);
});
});
+
+ it(`cancel beginStroke.`, () => {
+ const endStroke: EventListener = jest.fn();
+ const cancelEvent: EventListener = jest.fn((evt: Event): void => {
+ evt.preventDefault();
+ });
+
+ signpad.addEventListener('beginStroke', cancelEvent);
+ signpad.addEventListener('endStroke', endStroke);
+
+ canvas.dispatchEvent(
+ new PointerEvent('pointerdown', {
+ clientX: 50,
+ clientY: 30,
+ pressure: 1,
+ }),
+ );
+ canvas.dispatchEvent(
+ new PointerEvent('pointermove', {
+ clientX: 50,
+ clientY: 40,
+ pressure: 1,
+ }),
+ );
+ document.dispatchEvent(
+ new PointerEvent('pointerup', {
+ clientX: 50,
+ clientY: 40,
+ pressure: 1,
+ }),
+ );
+
+ expect(cancelEvent).toHaveBeenCalled();
+ expect(endStroke).not.toHaveBeenCalled();
+ expect(signpad.isEmpty()).toBe(true);
+
+ signpad.removeEventListener('beginStroke', cancelEvent);
+ signpad.removeEventListener('endStroke', endStroke);
+ });
});