Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

signature_pad

Package Overview
Dependencies
Maintainers
1
Versions
57
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

signature_pad - npm Package Compare versions

Comparing version 3.0.0-beta.4 to 4.0.0

224

dist/signature_pad.js
/*!
* Signature Pad v3.0.0-beta.4 | https://github.com/szimek/signature_pad
* (c) 2020 Szymon Nowak | Released under the MIT license
* Signature Pad v4.0.0 | https://github.com/szimek/signature_pad
* (c) 2021 Szymon Nowak | Released under the MIT license
*/
class Point {
constructor(x, y, time) {
this.x = x;
this.y = y;
constructor(x, y, pressure, time) {
if (isNaN(x) || isNaN(y)) {
throw new Error(`Point is invalid: (${x}, ${y})`);
}
this.x = +x;
this.y = +y;
this.pressure = pressure || 0;
this.time = time || Date.now();

@@ -16,3 +20,6 @@ }

equals(other) {
return this.x === other.x && this.y === other.y && this.time === other.time;
return (this.x === other.x &&
this.y === other.y &&
this.pressure === other.pressure &&
this.time === other.time);
}

@@ -126,9 +133,10 @@ velocityFrom(start) {

class SignaturePad {
class SignaturePad extends EventTarget {
constructor(canvas, options = {}) {
super();
this.canvas = canvas;
this.options = options;
this._handleMouseDown = (event) => {
if (event.which === 1) {
this._mouseButtonDown = true;
if (event.buttons === 1) {
this._drawningStroke = true;
this._strokeBegin(event);

@@ -138,3 +146,3 @@ }

this._handleMouseMove = (event) => {
if (this._mouseButtonDown) {
if (this._drawningStroke) {
this._strokeMoveUpdate(event);

@@ -144,4 +152,4 @@ }

this._handleMouseUp = (event) => {
if (event.which === 1 && this._mouseButtonDown) {
this._mouseButtonDown = false;
if (event.buttons === 1 && this._drawningStroke) {
this._drawningStroke = false;
this._strokeEnd(event);

@@ -170,2 +178,21 @@ }

};
this._handlePointerStart = (event) => {
this._drawningStroke = true;
event.preventDefault();
this._strokeBegin(event);
};
this._handlePointerMove = (event) => {
if (this._drawningStroke) {
event.preventDefault();
this._strokeMoveUpdate(event);
}
};
this._handlePointerEnd = (event) => {
this._drawningStroke = false;
const wasCanvasTouched = event.target === this.canvas;
if (wasCanvasTouched) {
event.preventDefault();
this._strokeEnd(event);
}
};
this.velocityFilterWeight = options.velocityFilterWeight || 0.7;

@@ -175,14 +202,6 @@ this.minWidth = options.minWidth || 0.5;

this.throttle = ('throttle' in options ? options.throttle : 16);
this.minDistance = ('minDistance' in options
? options.minDistance
: 5);
this.dotSize =
options.dotSize ||
function dotSize() {
return (this.minWidth + this.maxWidth) / 2;
};
this.minDistance = ('minDistance' in options ? options.minDistance : 5);
this.dotSize = options.dotSize || 0;
this.penColor = options.penColor || 'black';
this.backgroundColor = options.backgroundColor || 'rgba(0,0,0,0)';
this.onBegin = options.onBegin;
this.onEnd = options.onEnd;
this._strokeMoveUpdate = this.throttle

@@ -204,21 +223,22 @@ ? throttle(SignaturePad.prototype._strokeUpdate, this.throttle)

}
fromDataURL(dataUrl, options = {}, callback) {
const image = new Image();
const ratio = options.ratio || window.devicePixelRatio || 1;
const width = options.width || this.canvas.width / ratio;
const height = options.height || this.canvas.height / ratio;
this._reset();
image.onload = () => {
this._ctx.drawImage(image, 0, 0, width, height);
if (callback) {
callback();
}
};
image.onerror = (error) => {
if (callback) {
callback(error);
}
};
image.src = dataUrl;
this._isEmpty = false;
fromDataURL(dataUrl, options = {}) {
return new Promise((resolve, reject) => {
const image = new Image();
const ratio = options.ratio || window.devicePixelRatio || 1;
const width = options.width || this.canvas.width / ratio;
const height = options.height || this.canvas.height / ratio;
const xOffset = options.xOffset || 0;
const yOffset = options.yOffset || 0;
this._reset();
image.onload = () => {
this._ctx.drawImage(image, xOffset, yOffset, width, height);
resolve();
};
image.onerror = (error) => {
reject(error);
};
image.crossOrigin = 'anonymous';
image.src = dataUrl;
this._isEmpty = false;
});
}

@@ -249,5 +269,5 @@ toDataURL(type = 'image/png', encoderOptions) {

this.canvas.style.msTouchAction = 'auto';
this.canvas.removeEventListener('pointerdown', this._handleMouseDown);
this.canvas.removeEventListener('pointermove', this._handleMouseMove);
document.removeEventListener('pointerup', this._handleMouseUp);
this.canvas.removeEventListener('pointerdown', this._handlePointerStart);
this.canvas.removeEventListener('pointermove', this._handlePointerMove);
document.removeEventListener('pointerup', this._handlePointerEnd);
this.canvas.removeEventListener('mousedown', this._handleMouseDown);

@@ -263,6 +283,8 @@ this.canvas.removeEventListener('mousemove', this._handleMouseMove);

}
fromData(pointGroups) {
this.clear();
this._fromData(pointGroups, ({ color, curve }) => this._drawCurve({ color, curve }), ({ color, point }) => this._drawDot({ color, point }));
this._data = pointGroups;
fromData(pointGroups, { clear = true } = {}) {
if (clear) {
this.clear();
}
this._fromData(pointGroups, this._drawCurve.bind(this), this._drawDot.bind(this));
this._data = clear ? pointGroups : this._data.concat(pointGroups);
}

@@ -273,9 +295,10 @@ toData() {

_strokeBegin(event) {
this.dispatchEvent(new CustomEvent('beginStroke', { detail: event }));
const newPointGroup = {
color: this.penColor,
dotSize: this.dotSize,
minWidth: this.minWidth,
maxWidth: this.maxWidth,
penColor: this.penColor,
points: [],
};
if (typeof this.onBegin === 'function') {
this.onBegin(event);
}
this._data.push(newPointGroup);

@@ -290,5 +313,11 @@ this._reset();

}
this.dispatchEvent(new CustomEvent('beforeUpdateStroke', { detail: event }));
const x = event.clientX;
const y = event.clientY;
const point = this._createPoint(x, y);
const pressure = event.pressure !== undefined
? event.pressure
: event.force !== undefined
? event.force
: 0;
const point = this._createPoint(x, y, pressure);
const lastPointGroup = this._data[this._data.length - 1];

@@ -300,10 +329,20 @@ const lastPoints = lastPointGroup.points;

: false;
const color = lastPointGroup.color;
const { penColor, dotSize, minWidth, maxWidth } = lastPointGroup;
if (!lastPoint || !(lastPoint && isLastPointTooClose)) {
const curve = this._addPoint(point);
if (!lastPoint) {
this._drawDot({ color, point });
this._drawDot(point, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}
else if (curve) {
this._drawCurve({ color, curve });
this._drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -314,19 +353,19 @@ lastPoints.push({

y: point.y,
pressure: point.pressure,
});
}
this.dispatchEvent(new CustomEvent('afterUpdateStroke', { detail: event }));
}
_strokeEnd(event) {
this._strokeUpdate(event);
if (typeof this.onEnd === 'function') {
this.onEnd(event);
}
this.dispatchEvent(new CustomEvent('endStroke', { detail: event }));
}
_handlePointerEvents() {
this._mouseButtonDown = false;
this.canvas.addEventListener('pointerdown', this._handleMouseDown);
this.canvas.addEventListener('pointermove', this._handleMouseMove);
document.addEventListener('pointerup', this._handleMouseUp);
this._drawningStroke = false;
this.canvas.addEventListener('pointerdown', this._handlePointerStart);
this.canvas.addEventListener('pointermove', this._handlePointerMove);
document.addEventListener('pointerup', this._handlePointerEnd);
}
_handleMouseEvents() {
this._mouseButtonDown = false;
this._drawningStroke = false;
this.canvas.addEventListener('mousedown', this._handleMouseDown);

@@ -347,5 +386,5 @@ this.canvas.addEventListener('mousemove', this._handleMouseMove);

}
_createPoint(x, y) {
_createPoint(x, y, pressure) {
const rect = this.canvas.getBoundingClientRect();
return new Point(x - rect.left, y - rect.top, new Date().getTime());
return new Point(x - rect.left, y - rect.top, pressure, new Date().getTime());
}

@@ -387,8 +426,8 @@ _addPoint(point) {

}
_drawCurve({ color, curve }) {
_drawCurve(curve, options) {
const ctx = this._ctx;
const widthDelta = curve.endWidth - curve.startWidth;
const drawSteps = Math.floor(curve.length()) * 2;
const drawSteps = Math.ceil(curve.length()) * 2;
ctx.beginPath();
ctx.fillStyle = color;
ctx.fillStyle = options.penColor;
for (let i = 0; i < drawSteps; i += 1) {

@@ -409,3 +448,3 @@ const t = i / drawSteps;

y += ttt * curve.endPoint.y;
const width = Math.min(curve.startWidth + ttt * widthDelta, this.maxWidth);
const width = Math.min(curve.startWidth + ttt * widthDelta, options.maxWidth);
this._drawCurveSegment(x, y, width);

@@ -416,9 +455,11 @@ }

}
_drawDot({ color, point, }) {
_drawDot(point, options) {
const ctx = this._ctx;
const width = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;
const width = options.dotSize > 0
? options.dotSize
: (options.minWidth + options.maxWidth) / 2;
ctx.beginPath();
this._drawCurveSegment(point.x, point.y, width);
ctx.closePath();
ctx.fillStyle = color;
ctx.fillStyle = options.penColor;
ctx.fill();

@@ -428,8 +469,8 @@ }

for (const group of pointGroups) {
const { color, points } = group;
const { penColor, dotSize, minWidth, maxWidth, points } = group;
if (points.length > 1) {
for (let j = 0; j < points.length; j += 1) {
const basicPoint = points[j];
const point = new Point(basicPoint.x, basicPoint.y, basicPoint.time);
this.penColor = color;
const point = new Point(basicPoint.x, basicPoint.y, basicPoint.pressure, basicPoint.time);
this.penColor = penColor;
if (j === 0) {

@@ -440,3 +481,8 @@ this._reset();

if (curve) {
drawCurve({ color, curve });
drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -447,5 +493,7 @@ }

this._reset();
drawDot({
color,
point: points[0],
drawDot(points[0], {
penColor,
dotSize,
minWidth,
maxWidth,
});

@@ -465,3 +513,3 @@ }

svg.setAttribute('height', this.canvas.height.toString());
this._fromData(pointGroups, ({ color, curve }) => {
this._fromData(pointGroups, (curve, { penColor }) => {
const path = document.createElement('path');

@@ -478,3 +526,3 @@ if (!isNaN(curve.control1.x) &&

path.setAttribute('stroke-width', (curve.endWidth * 2.25).toFixed(3));
path.setAttribute('stroke', color);
path.setAttribute('stroke', penColor);
path.setAttribute('fill', 'none');

@@ -484,9 +532,9 @@ path.setAttribute('stroke-linecap', 'round');

}
}, ({ color, point }) => {
}, (point, { penColor, dotSize, minWidth, maxWidth }) => {
const circle = document.createElement('circle');
const dotSize = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;
circle.setAttribute('r', dotSize.toString());
const size = dotSize > 0 ? dotSize : (minWidth + maxWidth) / 2;
circle.setAttribute('r', size.toString());
circle.setAttribute('cx', point.x.toString());
circle.setAttribute('cy', point.y.toString());
circle.setAttribute('fill', color);
circle.setAttribute('fill', penColor);
svg.appendChild(circle);

@@ -498,3 +546,3 @@ });

' xmlns:xlink="http://www.w3.org/1999/xlink"' +
` viewBox="${minX} ${minY} ${maxX} ${maxY}"` +
` viewBox="${minX} ${minY} ${this.canvas.width} ${this.canvas.height}"` +
` width="${maxX}"` +

@@ -519,3 +567,3 @@ ` height="${maxY}"` +

export default SignaturePad;
export { SignaturePad as default };
//# sourceMappingURL=signature_pad.js.map
/*!
* Signature Pad v3.0.0-beta.4 | https://github.com/szimek/signature_pad
* (c) 2020 Szymon Nowak | Released under the MIT license
* Signature Pad v4.0.0 | https://github.com/szimek/signature_pad
* (c) 2021 Szymon Nowak | Released under the MIT license
*/
class t{constructor(t,e,i){this.x=t,this.y=e,this.time=i||Date.now()}distanceTo(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))}equals(t){return this.x===t.x&&this.y===t.y&&this.time===t.time}velocityFrom(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):0}}class e{constructor(t,e,i,o,s,n){this.startPoint=t,this.control2=e,this.control1=i,this.endPoint=o,this.startWidth=s,this.endWidth=n}static fromPoints(t,i){const o=this.calculateControlPoints(t[0],t[1],t[2]).c2,s=this.calculateControlPoints(t[1],t[2],t[3]).c1;return new e(t[1],o,s,t[2],i.start,i.end)}static calculateControlPoints(e,i,o){const s=e.x-i.x,n=e.y-i.y,h=i.x-o.x,a=i.y-o.y,r=(e.x+i.x)/2,c=(e.y+i.y)/2,l=(i.x+o.x)/2,d=(i.y+o.y)/2,u=Math.sqrt(s*s+n*n),v=Math.sqrt(h*h+a*a),_=v/(u+v),m=l+(r-l)*_,p=d+(c-d)*_,w=i.x-m,g=i.y-p;return{c1:new t(r+w,c+g),c2:new t(l+w,d+g)}}length(){let t,e,i=0;for(let o=0;o<=10;o+=1){const s=o/10,n=this.point(s,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),h=this.point(s,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(o>0){const o=n-t,s=h-e;i+=Math.sqrt(o*o+s*s)}t=n,e=h}return i}point(t,e,i,o,s){return e*(1-t)*(1-t)*(1-t)+3*i*(1-t)*(1-t)*t+3*o*(1-t)*t*t+s*t*t*t}}class i{constructor(t,e={}){this.canvas=t,this.options=e,this._handleMouseDown=t=>{1===t.which&&(this._mouseButtonDown=!0,this._strokeBegin(t))},this._handleMouseMove=t=>{this._mouseButtonDown&&this._strokeMoveUpdate(t)},this._handleMouseUp=t=>{1===t.which&&this._mouseButtonDown&&(this._mouseButtonDown=!1,this._strokeEnd(t))},this._handleTouchStart=t=>{if(t.preventDefault(),1===t.targetTouches.length){const e=t.changedTouches[0];this._strokeBegin(e)}},this._handleTouchMove=t=>{t.preventDefault();const e=t.targetTouches[0];this._strokeMoveUpdate(e)},this._handleTouchEnd=t=>{if(t.target===this.canvas){t.preventDefault();const e=t.changedTouches[0];this._strokeEnd(e)}},this.velocityFilterWeight=e.velocityFilterWeight||.7,this.minWidth=e.minWidth||.5,this.maxWidth=e.maxWidth||2.5,this.throttle="throttle"in e?e.throttle:16,this.minDistance="minDistance"in e?e.minDistance:5,this.dotSize=e.dotSize||function(){return(this.minWidth+this.maxWidth)/2},this.penColor=e.penColor||"black",this.backgroundColor=e.backgroundColor||"rgba(0,0,0,0)",this.onBegin=e.onBegin,this.onEnd=e.onEnd,this._strokeMoveUpdate=this.throttle?function(t,e=250){let i,o,s,n=0,h=null;const a=()=>{n=Date.now(),h=null,i=t.apply(o,s),h||(o=null,s=[])};return function(...r){const c=Date.now(),l=e-(c-n);return o=this,s=r,l<=0||l>e?(h&&(clearTimeout(h),h=null),n=c,i=t.apply(o,s),h||(o=null,s=[])):h||(h=window.setTimeout(a,l)),i}}(i.prototype._strokeUpdate,this.throttle):i.prototype._strokeUpdate,this._ctx=t.getContext("2d"),this.clear(),this.on()}clear(){const{_ctx:t,canvas:e}=this;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(),this._isEmpty=!0}fromDataURL(t,e={},i){const o=new Image,s=e.ratio||window.devicePixelRatio||1,n=e.width||this.canvas.width/s,h=e.height||this.canvas.height/s;this._reset(),o.onload=()=>{this._ctx.drawImage(o,0,0,n,h),i&&i()},o.onerror=t=>{i&&i(t)},o.src=t,this._isEmpty=!1}toDataURL(t="image/png",e){switch(t){case"image/svg+xml":return this._toSVG();default:return this.canvas.toDataURL(t,e)}}on(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",window.PointerEvent?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.removeEventListener("pointerdown",this._handleMouseDown),this.canvas.removeEventListener("pointermove",this._handleMouseMove),document.removeEventListener("pointerup",this._handleMouseUp),this.canvas.removeEventListener("mousedown",this._handleMouseDown),this.canvas.removeEventListener("mousemove",this._handleMouseMove),document.removeEventListener("mouseup",this._handleMouseUp),this.canvas.removeEventListener("touchstart",this._handleTouchStart),this.canvas.removeEventListener("touchmove",this._handleTouchMove),this.canvas.removeEventListener("touchend",this._handleTouchEnd)}isEmpty(){return this._isEmpty}fromData(t){this.clear(),this._fromData(t,({color:t,curve:e})=>this._drawCurve({color:t,curve:e}),({color:t,point:e})=>this._drawDot({color:t,point:e})),this._data=t}toData(){return this._data}_strokeBegin(t){const e={color:this.penColor,points:[]};"function"==typeof this.onBegin&&this.onBegin(t),this._data.push(e),this._reset(),this._strokeUpdate(t)}_strokeUpdate(t){if(0===this._data.length)return void this._strokeBegin(t);const e=t.clientX,i=t.clientY,o=this._createPoint(e,i),s=this._data[this._data.length-1],n=s.points,h=n.length>0&&n[n.length-1],a=!!h&&o.distanceTo(h)<=this.minDistance,r=s.color;if(!h||!h||!a){const t=this._addPoint(o);h?t&&this._drawCurve({color:r,curve:t}):this._drawDot({color:r,point:o}),n.push({time:o.time,x:o.x,y:o.y})}}_strokeEnd(t){this._strokeUpdate(t),"function"==typeof this.onEnd&&this.onEnd(t)}_handlePointerEvents(){this._mouseButtonDown=!1,this.canvas.addEventListener("pointerdown",this._handleMouseDown),this.canvas.addEventListener("pointermove",this._handleMouseMove),document.addEventListener("pointerup",this._handleMouseUp)}_handleMouseEvents(){this._mouseButtonDown=!1,this.canvas.addEventListener("mousedown",this._handleMouseDown),this.canvas.addEventListener("mousemove",this._handleMouseMove),document.addEventListener("mouseup",this._handleMouseUp)}_handleTouchEvents(){this.canvas.addEventListener("touchstart",this._handleTouchStart),this.canvas.addEventListener("touchmove",this._handleTouchMove),this.canvas.addEventListener("touchend",this._handleTouchEnd)}_reset(){this._lastPoints=[],this._lastVelocity=0,this._lastWidth=(this.minWidth+this.maxWidth)/2,this._ctx.fillStyle=this.penColor}_createPoint(e,i){const o=this.canvas.getBoundingClientRect();return new t(e-o.left,i-o.top,(new Date).getTime())}_addPoint(t){const{_lastPoints:i}=this;if(i.push(t),i.length>2){3===i.length&&i.unshift(i[0]);const t=this._calculateCurveWidths(i[1],i[2]),o=e.fromPoints(i,t);return i.shift(),o}return null}_calculateCurveWidths(t,e){const i=this.velocityFilterWeight*e.velocityFrom(t)+(1-this.velocityFilterWeight)*this._lastVelocity,o=this._strokeWidth(i),s={end:o,start:this._lastWidth};return this._lastVelocity=i,this._lastWidth=o,s}_strokeWidth(t){return Math.max(this.maxWidth/(t+1),this.minWidth)}_drawCurveSegment(t,e,i){const o=this._ctx;o.moveTo(t,e),o.arc(t,e,i,0,2*Math.PI,!1),this._isEmpty=!1}_drawCurve({color:t,curve:e}){const i=this._ctx,o=e.endWidth-e.startWidth,s=2*Math.floor(e.length());i.beginPath(),i.fillStyle=t;for(let t=0;t<s;t+=1){const i=t/s,n=i*i,h=n*i,a=1-i,r=a*a,c=r*a;let l=c*e.startPoint.x;l+=3*r*i*e.control1.x,l+=3*a*n*e.control2.x,l+=h*e.endPoint.x;let d=c*e.startPoint.y;d+=3*r*i*e.control1.y,d+=3*a*n*e.control2.y,d+=h*e.endPoint.y;const u=Math.min(e.startWidth+h*o,this.maxWidth);this._drawCurveSegment(l,d,u)}i.closePath(),i.fill()}_drawDot({color:t,point:e}){const i=this._ctx,o="function"==typeof this.dotSize?this.dotSize():this.dotSize;i.beginPath(),this._drawCurveSegment(e.x,e.y,o),i.closePath(),i.fillStyle=t,i.fill()}_fromData(e,i,o){for(const s of e){const{color:e,points:n}=s;if(n.length>1)for(let o=0;o<n.length;o+=1){const s=n[o],h=new t(s.x,s.y,s.time);this.penColor=e,0===o&&this._reset();const a=this._addPoint(h);a&&i({color:e,curve:a})}else this._reset(),o({color:e,point:n[0]})}}_toSVG(){const t=this._data,e=Math.max(window.devicePixelRatio||1,1),i=this.canvas.width/e,o=this.canvas.height/e,s=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttribute("width",this.canvas.width.toString()),s.setAttribute("height",this.canvas.height.toString()),this._fromData(t,({color:t,curve:e})=>{const i=document.createElement("path");if(!(isNaN(e.control1.x)||isNaN(e.control1.y)||isNaN(e.control2.x)||isNaN(e.control2.y))){const o=`M ${e.startPoint.x.toFixed(3)},${e.startPoint.y.toFixed(3)} C ${e.control1.x.toFixed(3)},${e.control1.y.toFixed(3)} ${e.control2.x.toFixed(3)},${e.control2.y.toFixed(3)} ${e.endPoint.x.toFixed(3)},${e.endPoint.y.toFixed(3)}`;i.setAttribute("d",o),i.setAttribute("stroke-width",(2.25*e.endWidth).toFixed(3)),i.setAttribute("stroke",t),i.setAttribute("fill","none"),i.setAttribute("stroke-linecap","round"),s.appendChild(i)}},({color:t,point:e})=>{const i=document.createElement("circle"),o="function"==typeof this.dotSize?this.dotSize():this.dotSize;i.setAttribute("r",o.toString()),i.setAttribute("cx",e.x.toString()),i.setAttribute("cy",e.y.toString()),i.setAttribute("fill",t),s.appendChild(i)});const n=`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${i} ${o}" width="${i}" height="${o}">`;let h=s.innerHTML;if(void 0===h){const t=document.createElement("dummy"),e=s.childNodes;t.innerHTML="";for(let i=0;i<e.length;i+=1)t.appendChild(e[i].cloneNode(!0));h=t.innerHTML}return"data:image/svg+xml;base64,"+btoa(n+h+"</svg>")}}export default i;
class t{constructor(t,e,i,s){if(isNaN(t)||isNaN(e))throw new Error(`Point is invalid: (${t}, ${e})`);this.x=+t,this.y=+e,this.pressure=i||0,this.time=s||Date.now()}distanceTo(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))}equals(t){return this.x===t.x&&this.y===t.y&&this.pressure===t.pressure&&this.time===t.time}velocityFrom(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):0}}class e{constructor(t,e,i,s,n,o){this.startPoint=t,this.control2=e,this.control1=i,this.endPoint=s,this.startWidth=n,this.endWidth=o}static fromPoints(t,i){const s=this.calculateControlPoints(t[0],t[1],t[2]).c2,n=this.calculateControlPoints(t[1],t[2],t[3]).c1;return new e(t[1],s,n,t[2],i.start,i.end)}static calculateControlPoints(e,i,s){const n=e.x-i.x,o=e.y-i.y,h=i.x-s.x,r=i.y-s.y,a=(e.x+i.x)/2,d=(e.y+i.y)/2,l=(i.x+s.x)/2,c=(i.y+s.y)/2,u=Math.sqrt(n*n+o*o),v=Math.sqrt(h*h+r*r),m=v/(u+v),_=l+(a-l)*m,p=c+(d-c)*m,g=i.x-_,x=i.y-p;return{c1:new t(a+g,d+x),c2:new t(l+g,c+x)}}length(){let t,e,i=0;for(let s=0;s<=10;s+=1){const n=s/10,o=this.point(n,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),h=this.point(n,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(s>0){const s=o-t,n=h-e;i+=Math.sqrt(s*s+n*n)}t=o,e=h}return i}point(t,e,i,s,n){return e*(1-t)*(1-t)*(1-t)+3*i*(1-t)*(1-t)*t+3*s*(1-t)*t*t+n*t*t*t}}class i extends EventTarget{constructor(t,e={}){super(),this.canvas=t,this.options=e,this._handleMouseDown=t=>{1===t.buttons&&(this._drawningStroke=!0,this._strokeBegin(t))},this._handleMouseMove=t=>{this._drawningStroke&&this._strokeMoveUpdate(t)},this._handleMouseUp=t=>{1===t.buttons&&this._drawningStroke&&(this._drawningStroke=!1,this._strokeEnd(t))},this._handleTouchStart=t=>{if(t.preventDefault(),1===t.targetTouches.length){const e=t.changedTouches[0];this._strokeBegin(e)}},this._handleTouchMove=t=>{t.preventDefault();const e=t.targetTouches[0];this._strokeMoveUpdate(e)},this._handleTouchEnd=t=>{if(t.target===this.canvas){t.preventDefault();const e=t.changedTouches[0];this._strokeEnd(e)}},this._handlePointerStart=t=>{this._drawningStroke=!0,t.preventDefault(),this._strokeBegin(t)},this._handlePointerMove=t=>{this._drawningStroke&&(t.preventDefault(),this._strokeMoveUpdate(t))},this._handlePointerEnd=t=>{this._drawningStroke=!1;t.target===this.canvas&&(t.preventDefault(),this._strokeEnd(t))},this.velocityFilterWeight=e.velocityFilterWeight||.7,this.minWidth=e.minWidth||.5,this.maxWidth=e.maxWidth||2.5,this.throttle="throttle"in e?e.throttle:16,this.minDistance="minDistance"in e?e.minDistance:5,this.dotSize=e.dotSize||0,this.penColor=e.penColor||"black",this.backgroundColor=e.backgroundColor||"rgba(0,0,0,0)",this._strokeMoveUpdate=this.throttle?function(t,e=250){let i,s,n,o=0,h=null;const r=()=>{o=Date.now(),h=null,i=t.apply(s,n),h||(s=null,n=[])};return function(...a){const d=Date.now(),l=e-(d-o);return s=this,n=a,l<=0||l>e?(h&&(clearTimeout(h),h=null),o=d,i=t.apply(s,n),h||(s=null,n=[])):h||(h=window.setTimeout(r,l)),i}}(i.prototype._strokeUpdate,this.throttle):i.prototype._strokeUpdate,this._ctx=t.getContext("2d"),this.clear(),this.on()}clear(){const{_ctx:t,canvas:e}=this;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(),this._isEmpty=!0}fromDataURL(t,e={}){return new Promise((i,s)=>{const n=new Image,o=e.ratio||window.devicePixelRatio||1,h=e.width||this.canvas.width/o,r=e.height||this.canvas.height/o,a=e.xOffset||0,d=e.yOffset||0;this._reset(),n.onload=()=>{this._ctx.drawImage(n,a,d,h,r),i()},n.onerror=t=>{s(t)},n.crossOrigin="anonymous",n.src=t,this._isEmpty=!1})}toDataURL(t="image/png",e){switch(t){case"image/svg+xml":return this._toSVG();default:return this.canvas.toDataURL(t,e)}}on(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",window.PointerEvent?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.removeEventListener("pointerdown",this._handlePointerStart),this.canvas.removeEventListener("pointermove",this._handlePointerMove),document.removeEventListener("pointerup",this._handlePointerEnd),this.canvas.removeEventListener("mousedown",this._handleMouseDown),this.canvas.removeEventListener("mousemove",this._handleMouseMove),document.removeEventListener("mouseup",this._handleMouseUp),this.canvas.removeEventListener("touchstart",this._handleTouchStart),this.canvas.removeEventListener("touchmove",this._handleTouchMove),this.canvas.removeEventListener("touchend",this._handleTouchEnd)}isEmpty(){return this._isEmpty}fromData(t,{clear:e=!0}={}){e&&this.clear(),this._fromData(t,this._drawCurve.bind(this),this._drawDot.bind(this)),this._data=e?t:this._data.concat(t)}toData(){return this._data}_strokeBegin(t){this.dispatchEvent(new CustomEvent("beginStroke",{detail:t}));const e={dotSize:this.dotSize,minWidth:this.minWidth,maxWidth:this.maxWidth,penColor:this.penColor,points:[]};this._data.push(e),this._reset(),this._strokeUpdate(t)}_strokeUpdate(t){if(0===this._data.length)return void this._strokeBegin(t);this.dispatchEvent(new CustomEvent("beforeUpdateStroke",{detail:t}));const e=t.clientX,i=t.clientY,s=void 0!==t.pressure?t.pressure:void 0!==t.force?t.force:0,n=this._createPoint(e,i,s),o=this._data[this._data.length-1],h=o.points,r=h.length>0&&h[h.length-1],a=!!r&&n.distanceTo(r)<=this.minDistance,{penColor:d,dotSize:l,minWidth:c,maxWidth:u}=o;if(!r||!r||!a){const t=this._addPoint(n);r?t&&this._drawCurve(t,{penColor:d,dotSize:l,minWidth:c,maxWidth:u}):this._drawDot(n,{penColor:d,dotSize:l,minWidth:c,maxWidth:u}),h.push({time:n.time,x:n.x,y:n.y,pressure:n.pressure})}this.dispatchEvent(new CustomEvent("afterUpdateStroke",{detail:t}))}_strokeEnd(t){this._strokeUpdate(t),this.dispatchEvent(new CustomEvent("endStroke",{detail:t}))}_handlePointerEvents(){this._drawningStroke=!1,this.canvas.addEventListener("pointerdown",this._handlePointerStart),this.canvas.addEventListener("pointermove",this._handlePointerMove),document.addEventListener("pointerup",this._handlePointerEnd)}_handleMouseEvents(){this._drawningStroke=!1,this.canvas.addEventListener("mousedown",this._handleMouseDown),this.canvas.addEventListener("mousemove",this._handleMouseMove),document.addEventListener("mouseup",this._handleMouseUp)}_handleTouchEvents(){this.canvas.addEventListener("touchstart",this._handleTouchStart),this.canvas.addEventListener("touchmove",this._handleTouchMove),this.canvas.addEventListener("touchend",this._handleTouchEnd)}_reset(){this._lastPoints=[],this._lastVelocity=0,this._lastWidth=(this.minWidth+this.maxWidth)/2,this._ctx.fillStyle=this.penColor}_createPoint(e,i,s){const n=this.canvas.getBoundingClientRect();return new t(e-n.left,i-n.top,s,(new Date).getTime())}_addPoint(t){const{_lastPoints:i}=this;if(i.push(t),i.length>2){3===i.length&&i.unshift(i[0]);const t=this._calculateCurveWidths(i[1],i[2]),s=e.fromPoints(i,t);return i.shift(),s}return null}_calculateCurveWidths(t,e){const i=this.velocityFilterWeight*e.velocityFrom(t)+(1-this.velocityFilterWeight)*this._lastVelocity,s=this._strokeWidth(i),n={end:s,start:this._lastWidth};return this._lastVelocity=i,this._lastWidth=s,n}_strokeWidth(t){return Math.max(this.maxWidth/(t+1),this.minWidth)}_drawCurveSegment(t,e,i){const s=this._ctx;s.moveTo(t,e),s.arc(t,e,i,0,2*Math.PI,!1),this._isEmpty=!1}_drawCurve(t,e){const i=this._ctx,s=t.endWidth-t.startWidth,n=2*Math.ceil(t.length());i.beginPath(),i.fillStyle=e.penColor;for(let i=0;i<n;i+=1){const o=i/n,h=o*o,r=h*o,a=1-o,d=a*a,l=d*a;let c=l*t.startPoint.x;c+=3*d*o*t.control1.x,c+=3*a*h*t.control2.x,c+=r*t.endPoint.x;let u=l*t.startPoint.y;u+=3*d*o*t.control1.y,u+=3*a*h*t.control2.y,u+=r*t.endPoint.y;const v=Math.min(t.startWidth+r*s,e.maxWidth);this._drawCurveSegment(c,u,v)}i.closePath(),i.fill()}_drawDot(t,e){const i=this._ctx,s=e.dotSize>0?e.dotSize:(e.minWidth+e.maxWidth)/2;i.beginPath(),this._drawCurveSegment(t.x,t.y,s),i.closePath(),i.fillStyle=e.penColor,i.fill()}_fromData(e,i,s){for(const n of e){const{penColor:e,dotSize:o,minWidth:h,maxWidth:r,points:a}=n;if(a.length>1)for(let s=0;s<a.length;s+=1){const n=a[s],d=new t(n.x,n.y,n.pressure,n.time);this.penColor=e,0===s&&this._reset();const l=this._addPoint(d);l&&i(l,{penColor:e,dotSize:o,minWidth:h,maxWidth:r})}else this._reset(),s(a[0],{penColor:e,dotSize:o,minWidth:h,maxWidth:r})}}_toSVG(){const t=this._data,e=Math.max(window.devicePixelRatio||1,1),i=this.canvas.width/e,s=this.canvas.height/e,n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("width",this.canvas.width.toString()),n.setAttribute("height",this.canvas.height.toString()),this._fromData(t,(t,{penColor:e})=>{const i=document.createElement("path");if(!(isNaN(t.control1.x)||isNaN(t.control1.y)||isNaN(t.control2.x)||isNaN(t.control2.y))){const s=`M ${t.startPoint.x.toFixed(3)},${t.startPoint.y.toFixed(3)} C ${t.control1.x.toFixed(3)},${t.control1.y.toFixed(3)} ${t.control2.x.toFixed(3)},${t.control2.y.toFixed(3)} ${t.endPoint.x.toFixed(3)},${t.endPoint.y.toFixed(3)}`;i.setAttribute("d",s),i.setAttribute("stroke-width",(2.25*t.endWidth).toFixed(3)),i.setAttribute("stroke",e),i.setAttribute("fill","none"),i.setAttribute("stroke-linecap","round"),n.appendChild(i)}},(t,{penColor:e,dotSize:i,minWidth:s,maxWidth:o})=>{const h=document.createElement("circle"),r=i>0?i:(s+o)/2;h.setAttribute("r",r.toString()),h.setAttribute("cx",t.x.toString()),h.setAttribute("cy",t.y.toString()),h.setAttribute("fill",e),n.appendChild(h)});const o=`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${this.canvas.width} ${this.canvas.height}" width="${i}" height="${s}">`;let h=n.innerHTML;if(void 0===h){const t=document.createElement("dummy"),e=n.childNodes;t.innerHTML="";for(let i=0;i<e.length;i+=1)t.appendChild(e[i].cloneNode(!0));h=t.innerHTML}return"data:image/svg+xml;base64,"+btoa(o+h+"</svg>")}}export{i as default};
//# sourceMappingURL=signature_pad.min.js.map
/*!
* Signature Pad v3.0.0-beta.4 | https://github.com/szimek/signature_pad
* (c) 2020 Szymon Nowak | Released under the MIT license
* Signature Pad v4.0.0 | https://github.com/szimek/signature_pad
* (c) 2021 Szymon Nowak | Released under the MIT license
*/

@@ -10,26 +10,32 @@

(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SignaturePad = factory());
}(this, (function () { 'use strict';
})(this, (function () { 'use strict';
var Point = (function () {
function Point(x, y, time) {
this.x = x;
this.y = y;
class Point {
constructor(x, y, pressure, time) {
if (isNaN(x) || isNaN(y)) {
throw new Error(`Point is invalid: (${x}, ${y})`);
}
this.x = +x;
this.y = +y;
this.pressure = pressure || 0;
this.time = time || Date.now();
}
Point.prototype.distanceTo = function (start) {
distanceTo(start) {
return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
};
Point.prototype.equals = function (other) {
return this.x === other.x && this.y === other.y && this.time === other.time;
};
Point.prototype.velocityFrom = function (start) {
}
equals(other) {
return (this.x === other.x &&
this.y === other.y &&
this.pressure === other.pressure &&
this.time === other.time);
}
velocityFrom(start) {
return this.time !== start.time
? this.distanceTo(start) / (this.time - start.time)
: 0;
};
return Point;
}());
}
}
var Bezier = (function () {
function Bezier(startPoint, control2, control1, endPoint, startWidth, endWidth) {
class Bezier {
constructor(startPoint, control2, control1, endPoint, startWidth, endWidth) {
this.startPoint = startPoint;

@@ -42,39 +48,39 @@ this.control2 = control2;

}
Bezier.fromPoints = function (points, widths) {
var c2 = this.calculateControlPoints(points[0], points[1], points[2]).c2;
var c3 = this.calculateControlPoints(points[1], points[2], points[3]).c1;
static fromPoints(points, widths) {
const c2 = this.calculateControlPoints(points[0], points[1], points[2]).c2;
const c3 = this.calculateControlPoints(points[1], points[2], points[3]).c1;
return new Bezier(points[1], c2, c3, points[2], widths.start, widths.end);
};
Bezier.calculateControlPoints = function (s1, s2, s3) {
var dx1 = s1.x - s2.x;
var dy1 = s1.y - s2.y;
var dx2 = s2.x - s3.x;
var dy2 = s2.y - s3.y;
var m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
var m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };
var l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
var l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
var dxm = m1.x - m2.x;
var dym = m1.y - m2.y;
var k = l2 / (l1 + l2);
var cm = { x: m2.x + dxm * k, y: m2.y + dym * k };
var tx = s2.x - cm.x;
var ty = s2.y - cm.y;
}
static calculateControlPoints(s1, s2, s3) {
const dx1 = s1.x - s2.x;
const dy1 = s1.y - s2.y;
const dx2 = s2.x - s3.x;
const dy2 = s2.y - s3.y;
const m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
const m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };
const l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
const l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
const dxm = m1.x - m2.x;
const dym = m1.y - m2.y;
const k = l2 / (l1 + l2);
const cm = { x: m2.x + dxm * k, y: m2.y + dym * k };
const tx = s2.x - cm.x;
const ty = s2.y - cm.y;
return {
c1: new Point(m1.x + tx, m1.y + ty),
c2: new Point(m2.x + tx, m2.y + ty)
c2: new Point(m2.x + tx, m2.y + ty),
};
};
Bezier.prototype.length = function () {
var steps = 10;
var length = 0;
var px;
var py;
for (var i = 0; i <= steps; i += 1) {
var t = i / steps;
var cx = this.point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
var cy = this.point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
}
length() {
const steps = 10;
let length = 0;
let px;
let py;
for (let i = 0; i <= steps; i += 1) {
const t = i / steps;
const cx = this.point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
const cy = this.point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
if (i > 0) {
var xdiff = cx - px;
var ydiff = cy - py;
const xdiff = cx - px;
const ydiff = cy - py;
length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);

@@ -86,4 +92,4 @@ }

return length;
};
Bezier.prototype.point = function (t, start, c1, c2, end) {
}
point(t, start, c1, c2, end) {
return (start * (1.0 - t) * (1.0 - t) * (1.0 - t))

@@ -93,14 +99,12 @@ + (3.0 * c1 * (1.0 - t) * (1.0 - t) * t)

+ (end * t * t * t);
};
return Bezier;
}());
}
}
function throttle(fn, wait) {
if (wait === void 0) { wait = 250; }
var previous = 0;
var timeout = null;
var result;
var storedContext;
var storedArgs;
var later = function () {
function throttle(fn, wait = 250) {
let previous = 0;
let timeout = null;
let result;
let storedContext;
let storedArgs;
const later = () => {
previous = Date.now();

@@ -114,9 +118,5 @@ timeout = null;

};
return function wrapper() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var now = Date.now();
var remaining = wait - (now - previous);
return function wrapper(...args) {
const now = Date.now();
const remaining = wait - (now - previous);
storedContext = this;

@@ -143,45 +143,63 @@ storedArgs = args;

var SignaturePad = (function () {
function SignaturePad(canvas, options) {
var _this = this;
if (options === void 0) { options = {}; }
class SignaturePad extends EventTarget {
constructor(canvas, options = {}) {
super();
this.canvas = canvas;
this.options = options;
this._handleMouseDown = function (event) {
if (event.which === 1) {
_this._mouseButtonDown = true;
_this._strokeBegin(event);
this._handleMouseDown = (event) => {
if (event.buttons === 1) {
this._drawningStroke = true;
this._strokeBegin(event);
}
};
this._handleMouseMove = function (event) {
if (_this._mouseButtonDown) {
_this._strokeMoveUpdate(event);
this._handleMouseMove = (event) => {
if (this._drawningStroke) {
this._strokeMoveUpdate(event);
}
};
this._handleMouseUp = function (event) {
if (event.which === 1 && _this._mouseButtonDown) {
_this._mouseButtonDown = false;
_this._strokeEnd(event);
this._handleMouseUp = (event) => {
if (event.buttons === 1 && this._drawningStroke) {
this._drawningStroke = false;
this._strokeEnd(event);
}
};
this._handleTouchStart = function (event) {
this._handleTouchStart = (event) => {
event.preventDefault();
if (event.targetTouches.length === 1) {
var touch = event.changedTouches[0];
_this._strokeBegin(touch);
const touch = event.changedTouches[0];
this._strokeBegin(touch);
}
};
this._handleTouchMove = function (event) {
this._handleTouchMove = (event) => {
event.preventDefault();
var touch = event.targetTouches[0];
_this._strokeMoveUpdate(touch);
const touch = event.targetTouches[0];
this._strokeMoveUpdate(touch);
};
this._handleTouchEnd = function (event) {
var wasCanvasTouched = event.target === _this.canvas;
this._handleTouchEnd = (event) => {
const wasCanvasTouched = event.target === this.canvas;
if (wasCanvasTouched) {
event.preventDefault();
var touch = event.changedTouches[0];
_this._strokeEnd(touch);
const touch = event.changedTouches[0];
this._strokeEnd(touch);
}
};
this._handlePointerStart = (event) => {
this._drawningStroke = true;
event.preventDefault();
this._strokeBegin(event);
};
this._handlePointerMove = (event) => {
if (this._drawningStroke) {
event.preventDefault();
this._strokeMoveUpdate(event);
}
};
this._handlePointerEnd = (event) => {
this._drawningStroke = false;
const wasCanvasTouched = event.target === this.canvas;
if (wasCanvasTouched) {
event.preventDefault();
this._strokeEnd(event);
}
};
this.velocityFilterWeight = options.velocityFilterWeight || 0.7;

@@ -191,14 +209,6 @@ this.minWidth = options.minWidth || 0.5;

this.throttle = ('throttle' in options ? options.throttle : 16);
this.minDistance = ('minDistance' in options
? options.minDistance
: 5);
this.dotSize =
options.dotSize ||
function dotSize() {
return (this.minWidth + this.maxWidth) / 2;
};
this.minDistance = ('minDistance' in options ? options.minDistance : 5);
this.dotSize = options.dotSize || 0;
this.penColor = options.penColor || 'black';
this.backgroundColor = options.backgroundColor || 'rgba(0,0,0,0)';
this.onBegin = options.onBegin;
this.onEnd = options.onEnd;
this._strokeMoveUpdate = this.throttle

@@ -211,4 +221,4 @@ ? throttle(SignaturePad.prototype._strokeUpdate, this.throttle)

}
SignaturePad.prototype.clear = function () {
var _a = this, ctx = _a._ctx, canvas = _a.canvas;
clear() {
const { _ctx: ctx, canvas } = this;
ctx.fillStyle = this.backgroundColor;

@@ -220,27 +230,25 @@ ctx.clearRect(0, 0, canvas.width, canvas.height);

this._isEmpty = true;
};
SignaturePad.prototype.fromDataURL = function (dataUrl, options, callback) {
var _this = this;
if (options === void 0) { options = {}; }
var image = new Image();
var ratio = options.ratio || window.devicePixelRatio || 1;
var width = options.width || this.canvas.width / ratio;
var height = options.height || this.canvas.height / ratio;
this._reset();
image.onload = function () {
_this._ctx.drawImage(image, 0, 0, width, height);
if (callback) {
callback();
}
};
image.onerror = function (error) {
if (callback) {
callback(error);
}
};
image.src = dataUrl;
this._isEmpty = false;
};
SignaturePad.prototype.toDataURL = function (type, encoderOptions) {
if (type === void 0) { type = 'image/png'; }
}
fromDataURL(dataUrl, options = {}) {
return new Promise((resolve, reject) => {
const image = new Image();
const ratio = options.ratio || window.devicePixelRatio || 1;
const width = options.width || this.canvas.width / ratio;
const height = options.height || this.canvas.height / ratio;
const xOffset = options.xOffset || 0;
const yOffset = options.yOffset || 0;
this._reset();
image.onload = () => {
this._ctx.drawImage(image, xOffset, yOffset, width, height);
resolve();
};
image.onerror = (error) => {
reject(error);
};
image.crossOrigin = 'anonymous';
image.src = dataUrl;
this._isEmpty = false;
});
}
toDataURL(type = 'image/png', encoderOptions) {
switch (type) {

@@ -252,4 +260,4 @@ case 'image/svg+xml':

}
};
SignaturePad.prototype.on = function () {
}
on() {
this.canvas.style.touchAction = 'none';

@@ -266,9 +274,9 @@ this.canvas.style.msTouchAction = 'none';

}
};
SignaturePad.prototype.off = function () {
}
off() {
this.canvas.style.touchAction = 'auto';
this.canvas.style.msTouchAction = 'auto';
this.canvas.removeEventListener('pointerdown', this._handleMouseDown);
this.canvas.removeEventListener('pointermove', this._handleMouseMove);
document.removeEventListener('pointerup', this._handleMouseUp);
this.canvas.removeEventListener('pointerdown', this._handlePointerStart);
this.canvas.removeEventListener('pointermove', this._handlePointerMove);
document.removeEventListener('pointerup', this._handlePointerEnd);
this.canvas.removeEventListener('mousedown', this._handleMouseDown);

@@ -280,34 +288,30 @@ this.canvas.removeEventListener('mousemove', this._handleMouseMove);

this.canvas.removeEventListener('touchend', this._handleTouchEnd);
};
SignaturePad.prototype.isEmpty = function () {
}
isEmpty() {
return this._isEmpty;
};
SignaturePad.prototype.fromData = function (pointGroups) {
var _this = this;
this.clear();
this._fromData(pointGroups, function (_a) {
var color = _a.color, curve = _a.curve;
return _this._drawCurve({ color: color, curve: curve });
}, function (_a) {
var color = _a.color, point = _a.point;
return _this._drawDot({ color: color, point: point });
});
this._data = pointGroups;
};
SignaturePad.prototype.toData = function () {
}
fromData(pointGroups, { clear = true } = {}) {
if (clear) {
this.clear();
}
this._fromData(pointGroups, this._drawCurve.bind(this), this._drawDot.bind(this));
this._data = clear ? pointGroups : this._data.concat(pointGroups);
}
toData() {
return this._data;
};
SignaturePad.prototype._strokeBegin = function (event) {
var newPointGroup = {
color: this.penColor,
points: []
}
_strokeBegin(event) {
this.dispatchEvent(new CustomEvent('beginStroke', { detail: event }));
const newPointGroup = {
dotSize: this.dotSize,
minWidth: this.minWidth,
maxWidth: this.maxWidth,
penColor: this.penColor,
points: [],
};
if (typeof this.onBegin === 'function') {
this.onBegin(event);
}
this._data.push(newPointGroup);
this._reset();
this._strokeUpdate(event);
};
SignaturePad.prototype._strokeUpdate = function (event) {
}
_strokeUpdate(event) {
if (this._data.length === 0) {

@@ -317,19 +321,35 @@ this._strokeBegin(event);

}
var x = event.clientX;
var y = event.clientY;
var point = this._createPoint(x, y);
var lastPointGroup = this._data[this._data.length - 1];
var lastPoints = lastPointGroup.points;
var lastPoint = lastPoints.length > 0 && lastPoints[lastPoints.length - 1];
var isLastPointTooClose = lastPoint
this.dispatchEvent(new CustomEvent('beforeUpdateStroke', { detail: event }));
const x = event.clientX;
const y = event.clientY;
const pressure = event.pressure !== undefined
? event.pressure
: event.force !== undefined
? event.force
: 0;
const point = this._createPoint(x, y, pressure);
const lastPointGroup = this._data[this._data.length - 1];
const lastPoints = lastPointGroup.points;
const lastPoint = lastPoints.length > 0 && lastPoints[lastPoints.length - 1];
const isLastPointTooClose = lastPoint
? point.distanceTo(lastPoint) <= this.minDistance
: false;
var color = lastPointGroup.color;
const { penColor, dotSize, minWidth, maxWidth } = lastPointGroup;
if (!lastPoint || !(lastPoint && isLastPointTooClose)) {
var curve = this._addPoint(point);
const curve = this._addPoint(point);
if (!lastPoint) {
this._drawDot({ color: color, point: point });
this._drawDot(point, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}
else if (curve) {
this._drawCurve({ color: color, curve: curve });
this._drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -339,30 +359,30 @@ lastPoints.push({

x: point.x,
y: point.y
y: point.y,
pressure: point.pressure,
});
}
};
SignaturePad.prototype._strokeEnd = function (event) {
this.dispatchEvent(new CustomEvent('afterUpdateStroke', { detail: event }));
}
_strokeEnd(event) {
this._strokeUpdate(event);
if (typeof this.onEnd === 'function') {
this.onEnd(event);
}
};
SignaturePad.prototype._handlePointerEvents = function () {
this._mouseButtonDown = false;
this.canvas.addEventListener('pointerdown', this._handleMouseDown);
this.canvas.addEventListener('pointermove', this._handleMouseMove);
document.addEventListener('pointerup', this._handleMouseUp);
};
SignaturePad.prototype._handleMouseEvents = function () {
this._mouseButtonDown = false;
this.dispatchEvent(new CustomEvent('endStroke', { detail: event }));
}
_handlePointerEvents() {
this._drawningStroke = false;
this.canvas.addEventListener('pointerdown', this._handlePointerStart);
this.canvas.addEventListener('pointermove', this._handlePointerMove);
document.addEventListener('pointerup', this._handlePointerEnd);
}
_handleMouseEvents() {
this._drawningStroke = false;
this.canvas.addEventListener('mousedown', this._handleMouseDown);
this.canvas.addEventListener('mousemove', this._handleMouseMove);
document.addEventListener('mouseup', this._handleMouseUp);
};
SignaturePad.prototype._handleTouchEvents = function () {
}
_handleTouchEvents() {
this.canvas.addEventListener('touchstart', this._handleTouchStart);
this.canvas.addEventListener('touchmove', this._handleTouchMove);
this.canvas.addEventListener('touchend', this._handleTouchEnd);
};
SignaturePad.prototype._reset = function () {
}
_reset() {
this._lastPoints = [];

@@ -372,9 +392,9 @@ this._lastVelocity = 0;

this._ctx.fillStyle = this.penColor;
};
SignaturePad.prototype._createPoint = function (x, y) {
var rect = this.canvas.getBoundingClientRect();
return new Point(x - rect.left, y - rect.top, new Date().getTime());
};
SignaturePad.prototype._addPoint = function (point) {
var _lastPoints = this._lastPoints;
}
_createPoint(x, y, pressure) {
const rect = this.canvas.getBoundingClientRect();
return new Point(x - rect.left, y - rect.top, pressure, new Date().getTime());
}
_addPoint(point) {
const { _lastPoints } = this;
_lastPoints.push(point);

@@ -385,4 +405,4 @@ if (_lastPoints.length > 2) {

}
var widths = this._calculateCurveWidths(_lastPoints[1], _lastPoints[2]);
var curve = Bezier.fromPoints(_lastPoints, widths);
const widths = this._calculateCurveWidths(_lastPoints[1], _lastPoints[2]);
const curve = Bezier.fromPoints(_lastPoints, widths);
_lastPoints.shift();

@@ -392,10 +412,10 @@ return curve;

return null;
};
SignaturePad.prototype._calculateCurveWidths = function (startPoint, endPoint) {
var velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) +
}
_calculateCurveWidths(startPoint, endPoint) {
const velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) +
(1 - this.velocityFilterWeight) * this._lastVelocity;
var newWidth = this._strokeWidth(velocity);
var widths = {
const newWidth = this._strokeWidth(velocity);
const widths = {
end: newWidth,
start: this._lastWidth
start: this._lastWidth,
};

@@ -405,35 +425,34 @@ this._lastVelocity = velocity;

return widths;
};
SignaturePad.prototype._strokeWidth = function (velocity) {
}
_strokeWidth(velocity) {
return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
};
SignaturePad.prototype._drawCurveSegment = function (x, y, width) {
var ctx = this._ctx;
}
_drawCurveSegment(x, y, width) {
const ctx = this._ctx;
ctx.moveTo(x, y);
ctx.arc(x, y, width, 0, 2 * Math.PI, false);
this._isEmpty = false;
};
SignaturePad.prototype._drawCurve = function (_a) {
var color = _a.color, curve = _a.curve;
var ctx = this._ctx;
var widthDelta = curve.endWidth - curve.startWidth;
var drawSteps = Math.floor(curve.length()) * 2;
}
_drawCurve(curve, options) {
const ctx = this._ctx;
const widthDelta = curve.endWidth - curve.startWidth;
const drawSteps = Math.ceil(curve.length()) * 2;
ctx.beginPath();
ctx.fillStyle = color;
for (var i = 0; i < drawSteps; i += 1) {
var t = i / drawSteps;
var tt = t * t;
var ttt = tt * t;
var u = 1 - t;
var uu = u * u;
var uuu = uu * u;
var x = uuu * curve.startPoint.x;
ctx.fillStyle = options.penColor;
for (let i = 0; i < drawSteps; i += 1) {
const t = i / drawSteps;
const tt = t * t;
const ttt = tt * t;
const u = 1 - t;
const uu = u * u;
const uuu = uu * u;
let x = uuu * curve.startPoint.x;
x += 3 * uu * t * curve.control1.x;
x += 3 * u * tt * curve.control2.x;
x += ttt * curve.endPoint.x;
var y = uuu * curve.startPoint.y;
let y = uuu * curve.startPoint.y;
y += 3 * uu * t * curve.control1.y;
y += 3 * u * tt * curve.control2.y;
y += ttt * curve.endPoint.y;
var width = Math.min(curve.startWidth + ttt * widthDelta, this.maxWidth);
const width = Math.min(curve.startWidth + ttt * widthDelta, options.maxWidth);
this._drawCurveSegment(x, y, width);

@@ -443,28 +462,33 @@ }

ctx.fill();
};
SignaturePad.prototype._drawDot = function (_a) {
var color = _a.color, point = _a.point;
var ctx = this._ctx;
var width = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;
}
_drawDot(point, options) {
const ctx = this._ctx;
const width = options.dotSize > 0
? options.dotSize
: (options.minWidth + options.maxWidth) / 2;
ctx.beginPath();
this._drawCurveSegment(point.x, point.y, width);
ctx.closePath();
ctx.fillStyle = color;
ctx.fillStyle = options.penColor;
ctx.fill();
};
SignaturePad.prototype._fromData = function (pointGroups, drawCurve, drawDot) {
for (var _i = 0, pointGroups_1 = pointGroups; _i < pointGroups_1.length; _i++) {
var group = pointGroups_1[_i];
var color = group.color, points = group.points;
}
_fromData(pointGroups, drawCurve, drawDot) {
for (const group of pointGroups) {
const { penColor, dotSize, minWidth, maxWidth, points } = group;
if (points.length > 1) {
for (var j = 0; j < points.length; j += 1) {
var basicPoint = points[j];
var point = new Point(basicPoint.x, basicPoint.y, basicPoint.time);
this.penColor = color;
for (let j = 0; j < points.length; j += 1) {
const basicPoint = points[j];
const point = new Point(basicPoint.x, basicPoint.y, basicPoint.pressure, basicPoint.time);
this.penColor = penColor;
if (j === 0) {
this._reset();
}
var curve = this._addPoint(point);
const curve = this._addPoint(point);
if (curve) {
drawCurve({ color: color, curve: curve });
drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -475,23 +499,23 @@ }

this._reset();
drawDot({
color: color,
point: points[0]
drawDot(points[0], {
penColor,
dotSize,
minWidth,
maxWidth,
});
}
}
};
SignaturePad.prototype._toSVG = function () {
var _this = this;
var pointGroups = this._data;
var ratio = Math.max(window.devicePixelRatio || 1, 1);
var minX = 0;
var minY = 0;
var maxX = this.canvas.width / ratio;
var maxY = this.canvas.height / ratio;
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
}
_toSVG() {
const pointGroups = this._data;
const ratio = Math.max(window.devicePixelRatio || 1, 1);
const minX = 0;
const minY = 0;
const maxX = this.canvas.width / ratio;
const maxY = this.canvas.height / ratio;
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', this.canvas.width.toString());
svg.setAttribute('height', this.canvas.height.toString());
this._fromData(pointGroups, function (_a) {
var color = _a.color, curve = _a.curve;
var path = document.createElement('path');
this._fromData(pointGroups, (curve, { penColor }) => {
const path = document.createElement('path');
if (!isNaN(curve.control1.x) &&

@@ -501,9 +525,9 @@ !isNaN(curve.control1.y) &&

!isNaN(curve.control2.y)) {
var attr = "M " + curve.startPoint.x.toFixed(3) + "," + curve.startPoint.y.toFixed(3) + " " +
("C " + curve.control1.x.toFixed(3) + "," + curve.control1.y.toFixed(3) + " ") +
(curve.control2.x.toFixed(3) + "," + curve.control2.y.toFixed(3) + " ") +
(curve.endPoint.x.toFixed(3) + "," + curve.endPoint.y.toFixed(3));
const attr = `M ${curve.startPoint.x.toFixed(3)},${curve.startPoint.y.toFixed(3)} ` +
`C ${curve.control1.x.toFixed(3)},${curve.control1.y.toFixed(3)} ` +
`${curve.control2.x.toFixed(3)},${curve.control2.y.toFixed(3)} ` +
`${curve.endPoint.x.toFixed(3)},${curve.endPoint.y.toFixed(3)}`;
path.setAttribute('d', attr);
path.setAttribute('stroke-width', (curve.endWidth * 2.25).toFixed(3));
path.setAttribute('stroke', color);
path.setAttribute('stroke', penColor);
path.setAttribute('fill', 'none');

@@ -513,26 +537,25 @@ path.setAttribute('stroke-linecap', 'round');

}
}, function (_a) {
var color = _a.color, point = _a.point;
var circle = document.createElement('circle');
var dotSize = typeof _this.dotSize === 'function' ? _this.dotSize() : _this.dotSize;
circle.setAttribute('r', dotSize.toString());
}, (point, { penColor, dotSize, minWidth, maxWidth }) => {
const circle = document.createElement('circle');
const size = dotSize > 0 ? dotSize : (minWidth + maxWidth) / 2;
circle.setAttribute('r', size.toString());
circle.setAttribute('cx', point.x.toString());
circle.setAttribute('cy', point.y.toString());
circle.setAttribute('fill', color);
circle.setAttribute('fill', penColor);
svg.appendChild(circle);
});
var prefix = 'data:image/svg+xml;base64,';
var header = '<svg' +
const prefix = 'data:image/svg+xml;base64,';
const header = '<svg' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink"' +
(" viewBox=\"" + minX + " " + minY + " " + maxX + " " + maxY + "\"") +
(" width=\"" + maxX + "\"") +
(" height=\"" + maxY + "\"") +
` viewBox="${minX} ${minY} ${this.canvas.width} ${this.canvas.height}"` +
` width="${maxX}"` +
` height="${maxY}"` +
'>';
var body = svg.innerHTML;
let body = svg.innerHTML;
if (body === undefined) {
var dummy = document.createElement('dummy');
var nodes = svg.childNodes;
const dummy = document.createElement('dummy');
const nodes = svg.childNodes;
dummy.innerHTML = '';
for (var i = 0; i < nodes.length; i += 1) {
for (let i = 0; i < nodes.length; i += 1) {
dummy.appendChild(nodes[i].cloneNode(true));

@@ -542,12 +565,11 @@ }

}
var footer = '</svg>';
var data = header + body + footer;
const footer = '</svg>';
const data = header + body + footer;
return prefix + btoa(data);
};
return SignaturePad;
}());
}
}
return SignaturePad;
})));
}));
//# sourceMappingURL=signature_pad.umd.js.map
/*!
* Signature Pad v3.0.0-beta.4 | https://github.com/szimek/signature_pad
* (c) 2020 Szymon Nowak | Released under the MIT license
* Signature Pad v4.0.0 | https://github.com/szimek/signature_pad
* (c) 2021 Szymon Nowak | Released under the MIT license
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).SignaturePad=e()}(this,(function(){"use strict";var t=function(){function t(t,e,o){this.x=t,this.y=e,this.time=o||Date.now()}return t.prototype.distanceTo=function(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))},t.prototype.equals=function(t){return this.x===t.x&&this.y===t.y&&this.time===t.time},t.prototype.velocityFrom=function(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):0},t}(),e=function(){function e(t,e,o,i,n,s){this.startPoint=t,this.control2=e,this.control1=o,this.endPoint=i,this.startWidth=n,this.endWidth=s}return e.fromPoints=function(t,o){var i=this.calculateControlPoints(t[0],t[1],t[2]).c2,n=this.calculateControlPoints(t[1],t[2],t[3]).c1;return new e(t[1],i,n,t[2],o.start,o.end)},e.calculateControlPoints=function(e,o,i){var n=e.x-o.x,s=e.y-o.y,r=o.x-i.x,h=o.y-i.y,a=(e.x+o.x)/2,c=(e.y+o.y)/2,u=(o.x+i.x)/2,d=(o.y+i.y)/2,l=Math.sqrt(n*n+s*s),v=Math.sqrt(r*r+h*h),p=v/(l+v),f=u+(a-u)*p,_=d+(c-d)*p,m=o.x-f,y=o.y-_;return{c1:new t(a+m,c+y),c2:new t(u+m,d+y)}},e.prototype.length=function(){for(var t,e,o=0,i=0;i<=10;i+=1){var n=i/10,s=this.point(n,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),r=this.point(n,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(i>0){var h=s-t,a=r-e;o+=Math.sqrt(h*h+a*a)}t=s,e=r}return o},e.prototype.point=function(t,e,o,i,n){return e*(1-t)*(1-t)*(1-t)+3*o*(1-t)*(1-t)*t+3*i*(1-t)*t*t+n*t*t*t},e}();return function(){function o(t,e){var i=this;void 0===e&&(e={}),this.canvas=t,this.options=e,this._handleMouseDown=function(t){1===t.which&&(i._mouseButtonDown=!0,i._strokeBegin(t))},this._handleMouseMove=function(t){i._mouseButtonDown&&i._strokeMoveUpdate(t)},this._handleMouseUp=function(t){1===t.which&&i._mouseButtonDown&&(i._mouseButtonDown=!1,i._strokeEnd(t))},this._handleTouchStart=function(t){if(t.preventDefault(),1===t.targetTouches.length){var e=t.changedTouches[0];i._strokeBegin(e)}},this._handleTouchMove=function(t){t.preventDefault();var e=t.targetTouches[0];i._strokeMoveUpdate(e)},this._handleTouchEnd=function(t){if(t.target===i.canvas){t.preventDefault();var e=t.changedTouches[0];i._strokeEnd(e)}},this.velocityFilterWeight=e.velocityFilterWeight||.7,this.minWidth=e.minWidth||.5,this.maxWidth=e.maxWidth||2.5,this.throttle="throttle"in e?e.throttle:16,this.minDistance="minDistance"in e?e.minDistance:5,this.dotSize=e.dotSize||function(){return(this.minWidth+this.maxWidth)/2},this.penColor=e.penColor||"black",this.backgroundColor=e.backgroundColor||"rgba(0,0,0,0)",this.onBegin=e.onBegin,this.onEnd=e.onEnd,this._strokeMoveUpdate=this.throttle?function(t,e){void 0===e&&(e=250);var o,i,n,s=0,r=null,h=function(){s=Date.now(),r=null,o=t.apply(i,n),r||(i=null,n=[])};return function(){for(var a=[],c=0;c<arguments.length;c++)a[c]=arguments[c];var u=Date.now(),d=e-(u-s);return i=this,n=a,d<=0||d>e?(r&&(clearTimeout(r),r=null),s=u,o=t.apply(i,n),r||(i=null,n=[])):r||(r=window.setTimeout(h,d)),o}}(o.prototype._strokeUpdate,this.throttle):o.prototype._strokeUpdate,this._ctx=t.getContext("2d"),this.clear(),this.on()}return o.prototype.clear=function(){var t=this._ctx,e=this.canvas;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(),this._isEmpty=!0},o.prototype.fromDataURL=function(t,e,o){var i=this;void 0===e&&(e={});var n=new Image,s=e.ratio||window.devicePixelRatio||1,r=e.width||this.canvas.width/s,h=e.height||this.canvas.height/s;this._reset(),n.onload=function(){i._ctx.drawImage(n,0,0,r,h),o&&o()},n.onerror=function(t){o&&o(t)},n.src=t,this._isEmpty=!1},o.prototype.toDataURL=function(t,e){switch(void 0===t&&(t="image/png"),t){case"image/svg+xml":return this._toSVG();default:return this.canvas.toDataURL(t,e)}},o.prototype.on=function(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",window.PointerEvent?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())},o.prototype.off=function(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.removeEventListener("pointerdown",this._handleMouseDown),this.canvas.removeEventListener("pointermove",this._handleMouseMove),document.removeEventListener("pointerup",this._handleMouseUp),this.canvas.removeEventListener("mousedown",this._handleMouseDown),this.canvas.removeEventListener("mousemove",this._handleMouseMove),document.removeEventListener("mouseup",this._handleMouseUp),this.canvas.removeEventListener("touchstart",this._handleTouchStart),this.canvas.removeEventListener("touchmove",this._handleTouchMove),this.canvas.removeEventListener("touchend",this._handleTouchEnd)},o.prototype.isEmpty=function(){return this._isEmpty},o.prototype.fromData=function(t){var e=this;this.clear(),this._fromData(t,(function(t){var o=t.color,i=t.curve;return e._drawCurve({color:o,curve:i})}),(function(t){var o=t.color,i=t.point;return e._drawDot({color:o,point:i})})),this._data=t},o.prototype.toData=function(){return this._data},o.prototype._strokeBegin=function(t){var e={color:this.penColor,points:[]};"function"==typeof this.onBegin&&this.onBegin(t),this._data.push(e),this._reset(),this._strokeUpdate(t)},o.prototype._strokeUpdate=function(t){if(0!==this._data.length){var e=t.clientX,o=t.clientY,i=this._createPoint(e,o),n=this._data[this._data.length-1],s=n.points,r=s.length>0&&s[s.length-1],h=!!r&&i.distanceTo(r)<=this.minDistance,a=n.color;if(!r||!r||!h){var c=this._addPoint(i);r?c&&this._drawCurve({color:a,curve:c}):this._drawDot({color:a,point:i}),s.push({time:i.time,x:i.x,y:i.y})}}else this._strokeBegin(t)},o.prototype._strokeEnd=function(t){this._strokeUpdate(t),"function"==typeof this.onEnd&&this.onEnd(t)},o.prototype._handlePointerEvents=function(){this._mouseButtonDown=!1,this.canvas.addEventListener("pointerdown",this._handleMouseDown),this.canvas.addEventListener("pointermove",this._handleMouseMove),document.addEventListener("pointerup",this._handleMouseUp)},o.prototype._handleMouseEvents=function(){this._mouseButtonDown=!1,this.canvas.addEventListener("mousedown",this._handleMouseDown),this.canvas.addEventListener("mousemove",this._handleMouseMove),document.addEventListener("mouseup",this._handleMouseUp)},o.prototype._handleTouchEvents=function(){this.canvas.addEventListener("touchstart",this._handleTouchStart),this.canvas.addEventListener("touchmove",this._handleTouchMove),this.canvas.addEventListener("touchend",this._handleTouchEnd)},o.prototype._reset=function(){this._lastPoints=[],this._lastVelocity=0,this._lastWidth=(this.minWidth+this.maxWidth)/2,this._ctx.fillStyle=this.penColor},o.prototype._createPoint=function(e,o){var i=this.canvas.getBoundingClientRect();return new t(e-i.left,o-i.top,(new Date).getTime())},o.prototype._addPoint=function(t){var o=this._lastPoints;if(o.push(t),o.length>2){3===o.length&&o.unshift(o[0]);var i=this._calculateCurveWidths(o[1],o[2]),n=e.fromPoints(o,i);return o.shift(),n}return null},o.prototype._calculateCurveWidths=function(t,e){var o=this.velocityFilterWeight*e.velocityFrom(t)+(1-this.velocityFilterWeight)*this._lastVelocity,i=this._strokeWidth(o),n={end:i,start:this._lastWidth};return this._lastVelocity=o,this._lastWidth=i,n},o.prototype._strokeWidth=function(t){return Math.max(this.maxWidth/(t+1),this.minWidth)},o.prototype._drawCurveSegment=function(t,e,o){var i=this._ctx;i.moveTo(t,e),i.arc(t,e,o,0,2*Math.PI,!1),this._isEmpty=!1},o.prototype._drawCurve=function(t){var e=t.color,o=t.curve,i=this._ctx,n=o.endWidth-o.startWidth,s=2*Math.floor(o.length());i.beginPath(),i.fillStyle=e;for(var r=0;r<s;r+=1){var h=r/s,a=h*h,c=a*h,u=1-h,d=u*u,l=d*u,v=l*o.startPoint.x;v+=3*d*h*o.control1.x,v+=3*u*a*o.control2.x,v+=c*o.endPoint.x;var p=l*o.startPoint.y;p+=3*d*h*o.control1.y,p+=3*u*a*o.control2.y,p+=c*o.endPoint.y;var f=Math.min(o.startWidth+c*n,this.maxWidth);this._drawCurveSegment(v,p,f)}i.closePath(),i.fill()},o.prototype._drawDot=function(t){var e=t.color,o=t.point,i=this._ctx,n="function"==typeof this.dotSize?this.dotSize():this.dotSize;i.beginPath(),this._drawCurveSegment(o.x,o.y,n),i.closePath(),i.fillStyle=e,i.fill()},o.prototype._fromData=function(e,o,i){for(var n=0,s=e;n<s.length;n++){var r=s[n],h=r.color,a=r.points;if(a.length>1)for(var c=0;c<a.length;c+=1){var u=a[c],d=new t(u.x,u.y,u.time);this.penColor=h,0===c&&this._reset();var l=this._addPoint(d);l&&o({color:h,curve:l})}else this._reset(),i({color:h,point:a[0]})}},o.prototype._toSVG=function(){var t=this,e=this._data,o=Math.max(window.devicePixelRatio||1,1),i=this.canvas.width/o,n=this.canvas.height/o,s=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttribute("width",this.canvas.width.toString()),s.setAttribute("height",this.canvas.height.toString()),this._fromData(e,(function(t){var e=t.color,o=t.curve,i=document.createElement("path");if(!(isNaN(o.control1.x)||isNaN(o.control1.y)||isNaN(o.control2.x)||isNaN(o.control2.y))){var n="M "+o.startPoint.x.toFixed(3)+","+o.startPoint.y.toFixed(3)+" C "+o.control1.x.toFixed(3)+","+o.control1.y.toFixed(3)+" "+o.control2.x.toFixed(3)+","+o.control2.y.toFixed(3)+" "+o.endPoint.x.toFixed(3)+","+o.endPoint.y.toFixed(3);i.setAttribute("d",n),i.setAttribute("stroke-width",(2.25*o.endWidth).toFixed(3)),i.setAttribute("stroke",e),i.setAttribute("fill","none"),i.setAttribute("stroke-linecap","round"),s.appendChild(i)}}),(function(e){var o=e.color,i=e.point,n=document.createElement("circle"),r="function"==typeof t.dotSize?t.dotSize():t.dotSize;n.setAttribute("r",r.toString()),n.setAttribute("cx",i.x.toString()),n.setAttribute("cy",i.y.toString()),n.setAttribute("fill",o),s.appendChild(n)}));var r='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 '+i+" "+n+'" width="'+i+'" height="'+n+'">',h=s.innerHTML;if(void 0===h){var a=document.createElement("dummy"),c=s.childNodes;a.innerHTML="";for(var u=0;u<c.length;u+=1)a.appendChild(c[u].cloneNode(!0));h=a.innerHTML}return"data:image/svg+xml;base64,"+btoa(r+h+"</svg>")},o}()}));
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).SignaturePad=e()}(this,(function(){"use strict";class t{constructor(t,e,i,n){if(isNaN(t)||isNaN(e))throw new Error(`Point is invalid: (${t}, ${e})`);this.x=+t,this.y=+e,this.pressure=i||0,this.time=n||Date.now()}distanceTo(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))}equals(t){return this.x===t.x&&this.y===t.y&&this.pressure===t.pressure&&this.time===t.time}velocityFrom(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):0}}class e{constructor(t,e,i,n,s,o){this.startPoint=t,this.control2=e,this.control1=i,this.endPoint=n,this.startWidth=s,this.endWidth=o}static fromPoints(t,i){const n=this.calculateControlPoints(t[0],t[1],t[2]).c2,s=this.calculateControlPoints(t[1],t[2],t[3]).c1;return new e(t[1],n,s,t[2],i.start,i.end)}static calculateControlPoints(e,i,n){const s=e.x-i.x,o=e.y-i.y,h=i.x-n.x,r=i.y-n.y,a=(e.x+i.x)/2,d=(e.y+i.y)/2,l=(i.x+n.x)/2,c=(i.y+n.y)/2,u=Math.sqrt(s*s+o*o),v=Math.sqrt(h*h+r*r),m=v/(u+v),_=l+(a-l)*m,p=c+(d-c)*m,g=i.x-_,x=i.y-p;return{c1:new t(a+g,d+x),c2:new t(l+g,c+x)}}length(){let t,e,i=0;for(let n=0;n<=10;n+=1){const s=n/10,o=this.point(s,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),h=this.point(s,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(n>0){const n=o-t,s=h-e;i+=Math.sqrt(n*n+s*s)}t=o,e=h}return i}point(t,e,i,n,s){return e*(1-t)*(1-t)*(1-t)+3*i*(1-t)*(1-t)*t+3*n*(1-t)*t*t+s*t*t*t}}class i extends EventTarget{constructor(t,e={}){super(),this.canvas=t,this.options=e,this._handleMouseDown=t=>{1===t.buttons&&(this._drawningStroke=!0,this._strokeBegin(t))},this._handleMouseMove=t=>{this._drawningStroke&&this._strokeMoveUpdate(t)},this._handleMouseUp=t=>{1===t.buttons&&this._drawningStroke&&(this._drawningStroke=!1,this._strokeEnd(t))},this._handleTouchStart=t=>{if(t.preventDefault(),1===t.targetTouches.length){const e=t.changedTouches[0];this._strokeBegin(e)}},this._handleTouchMove=t=>{t.preventDefault();const e=t.targetTouches[0];this._strokeMoveUpdate(e)},this._handleTouchEnd=t=>{if(t.target===this.canvas){t.preventDefault();const e=t.changedTouches[0];this._strokeEnd(e)}},this._handlePointerStart=t=>{this._drawningStroke=!0,t.preventDefault(),this._strokeBegin(t)},this._handlePointerMove=t=>{this._drawningStroke&&(t.preventDefault(),this._strokeMoveUpdate(t))},this._handlePointerEnd=t=>{this._drawningStroke=!1;t.target===this.canvas&&(t.preventDefault(),this._strokeEnd(t))},this.velocityFilterWeight=e.velocityFilterWeight||.7,this.minWidth=e.minWidth||.5,this.maxWidth=e.maxWidth||2.5,this.throttle="throttle"in e?e.throttle:16,this.minDistance="minDistance"in e?e.minDistance:5,this.dotSize=e.dotSize||0,this.penColor=e.penColor||"black",this.backgroundColor=e.backgroundColor||"rgba(0,0,0,0)",this._strokeMoveUpdate=this.throttle?function(t,e=250){let i,n,s,o=0,h=null;const r=()=>{o=Date.now(),h=null,i=t.apply(n,s),h||(n=null,s=[])};return function(...a){const d=Date.now(),l=e-(d-o);return n=this,s=a,l<=0||l>e?(h&&(clearTimeout(h),h=null),o=d,i=t.apply(n,s),h||(n=null,s=[])):h||(h=window.setTimeout(r,l)),i}}(i.prototype._strokeUpdate,this.throttle):i.prototype._strokeUpdate,this._ctx=t.getContext("2d"),this.clear(),this.on()}clear(){const{_ctx:t,canvas:e}=this;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(),this._isEmpty=!0}fromDataURL(t,e={}){return new Promise((i,n)=>{const s=new Image,o=e.ratio||window.devicePixelRatio||1,h=e.width||this.canvas.width/o,r=e.height||this.canvas.height/o,a=e.xOffset||0,d=e.yOffset||0;this._reset(),s.onload=()=>{this._ctx.drawImage(s,a,d,h,r),i()},s.onerror=t=>{n(t)},s.crossOrigin="anonymous",s.src=t,this._isEmpty=!1})}toDataURL(t="image/png",e){switch(t){case"image/svg+xml":return this._toSVG();default:return this.canvas.toDataURL(t,e)}}on(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",window.PointerEvent?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.removeEventListener("pointerdown",this._handlePointerStart),this.canvas.removeEventListener("pointermove",this._handlePointerMove),document.removeEventListener("pointerup",this._handlePointerEnd),this.canvas.removeEventListener("mousedown",this._handleMouseDown),this.canvas.removeEventListener("mousemove",this._handleMouseMove),document.removeEventListener("mouseup",this._handleMouseUp),this.canvas.removeEventListener("touchstart",this._handleTouchStart),this.canvas.removeEventListener("touchmove",this._handleTouchMove),this.canvas.removeEventListener("touchend",this._handleTouchEnd)}isEmpty(){return this._isEmpty}fromData(t,{clear:e=!0}={}){e&&this.clear(),this._fromData(t,this._drawCurve.bind(this),this._drawDot.bind(this)),this._data=e?t:this._data.concat(t)}toData(){return this._data}_strokeBegin(t){this.dispatchEvent(new CustomEvent("beginStroke",{detail:t}));const e={dotSize:this.dotSize,minWidth:this.minWidth,maxWidth:this.maxWidth,penColor:this.penColor,points:[]};this._data.push(e),this._reset(),this._strokeUpdate(t)}_strokeUpdate(t){if(0===this._data.length)return void this._strokeBegin(t);this.dispatchEvent(new CustomEvent("beforeUpdateStroke",{detail:t}));const e=t.clientX,i=t.clientY,n=void 0!==t.pressure?t.pressure:void 0!==t.force?t.force:0,s=this._createPoint(e,i,n),o=this._data[this._data.length-1],h=o.points,r=h.length>0&&h[h.length-1],a=!!r&&s.distanceTo(r)<=this.minDistance,{penColor:d,dotSize:l,minWidth:c,maxWidth:u}=o;if(!r||!r||!a){const t=this._addPoint(s);r?t&&this._drawCurve(t,{penColor:d,dotSize:l,minWidth:c,maxWidth:u}):this._drawDot(s,{penColor:d,dotSize:l,minWidth:c,maxWidth:u}),h.push({time:s.time,x:s.x,y:s.y,pressure:s.pressure})}this.dispatchEvent(new CustomEvent("afterUpdateStroke",{detail:t}))}_strokeEnd(t){this._strokeUpdate(t),this.dispatchEvent(new CustomEvent("endStroke",{detail:t}))}_handlePointerEvents(){this._drawningStroke=!1,this.canvas.addEventListener("pointerdown",this._handlePointerStart),this.canvas.addEventListener("pointermove",this._handlePointerMove),document.addEventListener("pointerup",this._handlePointerEnd)}_handleMouseEvents(){this._drawningStroke=!1,this.canvas.addEventListener("mousedown",this._handleMouseDown),this.canvas.addEventListener("mousemove",this._handleMouseMove),document.addEventListener("mouseup",this._handleMouseUp)}_handleTouchEvents(){this.canvas.addEventListener("touchstart",this._handleTouchStart),this.canvas.addEventListener("touchmove",this._handleTouchMove),this.canvas.addEventListener("touchend",this._handleTouchEnd)}_reset(){this._lastPoints=[],this._lastVelocity=0,this._lastWidth=(this.minWidth+this.maxWidth)/2,this._ctx.fillStyle=this.penColor}_createPoint(e,i,n){const s=this.canvas.getBoundingClientRect();return new t(e-s.left,i-s.top,n,(new Date).getTime())}_addPoint(t){const{_lastPoints:i}=this;if(i.push(t),i.length>2){3===i.length&&i.unshift(i[0]);const t=this._calculateCurveWidths(i[1],i[2]),n=e.fromPoints(i,t);return i.shift(),n}return null}_calculateCurveWidths(t,e){const i=this.velocityFilterWeight*e.velocityFrom(t)+(1-this.velocityFilterWeight)*this._lastVelocity,n=this._strokeWidth(i),s={end:n,start:this._lastWidth};return this._lastVelocity=i,this._lastWidth=n,s}_strokeWidth(t){return Math.max(this.maxWidth/(t+1),this.minWidth)}_drawCurveSegment(t,e,i){const n=this._ctx;n.moveTo(t,e),n.arc(t,e,i,0,2*Math.PI,!1),this._isEmpty=!1}_drawCurve(t,e){const i=this._ctx,n=t.endWidth-t.startWidth,s=2*Math.ceil(t.length());i.beginPath(),i.fillStyle=e.penColor;for(let i=0;i<s;i+=1){const o=i/s,h=o*o,r=h*o,a=1-o,d=a*a,l=d*a;let c=l*t.startPoint.x;c+=3*d*o*t.control1.x,c+=3*a*h*t.control2.x,c+=r*t.endPoint.x;let u=l*t.startPoint.y;u+=3*d*o*t.control1.y,u+=3*a*h*t.control2.y,u+=r*t.endPoint.y;const v=Math.min(t.startWidth+r*n,e.maxWidth);this._drawCurveSegment(c,u,v)}i.closePath(),i.fill()}_drawDot(t,e){const i=this._ctx,n=e.dotSize>0?e.dotSize:(e.minWidth+e.maxWidth)/2;i.beginPath(),this._drawCurveSegment(t.x,t.y,n),i.closePath(),i.fillStyle=e.penColor,i.fill()}_fromData(e,i,n){for(const s of e){const{penColor:e,dotSize:o,minWidth:h,maxWidth:r,points:a}=s;if(a.length>1)for(let n=0;n<a.length;n+=1){const s=a[n],d=new t(s.x,s.y,s.pressure,s.time);this.penColor=e,0===n&&this._reset();const l=this._addPoint(d);l&&i(l,{penColor:e,dotSize:o,minWidth:h,maxWidth:r})}else this._reset(),n(a[0],{penColor:e,dotSize:o,minWidth:h,maxWidth:r})}}_toSVG(){const t=this._data,e=Math.max(window.devicePixelRatio||1,1),i=this.canvas.width/e,n=this.canvas.height/e,s=document.createElementNS("http://www.w3.org/2000/svg","svg");s.setAttribute("width",this.canvas.width.toString()),s.setAttribute("height",this.canvas.height.toString()),this._fromData(t,(t,{penColor:e})=>{const i=document.createElement("path");if(!(isNaN(t.control1.x)||isNaN(t.control1.y)||isNaN(t.control2.x)||isNaN(t.control2.y))){const n=`M ${t.startPoint.x.toFixed(3)},${t.startPoint.y.toFixed(3)} C ${t.control1.x.toFixed(3)},${t.control1.y.toFixed(3)} ${t.control2.x.toFixed(3)},${t.control2.y.toFixed(3)} ${t.endPoint.x.toFixed(3)},${t.endPoint.y.toFixed(3)}`;i.setAttribute("d",n),i.setAttribute("stroke-width",(2.25*t.endWidth).toFixed(3)),i.setAttribute("stroke",e),i.setAttribute("fill","none"),i.setAttribute("stroke-linecap","round"),s.appendChild(i)}},(t,{penColor:e,dotSize:i,minWidth:n,maxWidth:o})=>{const h=document.createElement("circle"),r=i>0?i:(n+o)/2;h.setAttribute("r",r.toString()),h.setAttribute("cx",t.x.toString()),h.setAttribute("cy",t.y.toString()),h.setAttribute("fill",e),s.appendChild(h)});const o=`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${this.canvas.width} ${this.canvas.height}" width="${i}" height="${n}">`;let h=s.innerHTML;if(void 0===h){const t=document.createElement("dummy"),e=s.childNodes;t.innerHTML="";for(let i=0;i<e.length;i+=1)t.appendChild(e[i].cloneNode(!0));h=t.innerHTML}return"data:image/svg+xml;base64,"+btoa(o+h+"</svg>")}}return i}));
//# sourceMappingURL=signature_pad.umd.min.js.map
export interface BasicPoint {
x: number;
y: number;
pressure: number;
time: number;

@@ -9,4 +10,5 @@ }

y: number;
pressure: number;
time: number;
constructor(x: number, y: number, time?: number);
constructor(x: number, y: number, pressure?: number, time?: number);
distanceTo(start: BasicPoint): number;

@@ -13,0 +15,0 @@ equals(other: BasicPoint): boolean;

@@ -6,3 +6,3 @@ /**

* Implementation of interpolation using cubic Bézier curves is taken from:
* http://www.benknowscode.com/2012/09/path-interpolation-using-cubic-bezier_9742.html
* https://web.archive.org/web/20160323213433/http://www.benknowscode.com/2012/09/path-interpolation-using-cubic-bezier_9742.html
*

@@ -15,36 +15,37 @@ * Algorithm for approximated length of a Bézier curve is taken from:

interface CSSStyleDeclaration {
msTouchAction: string;
msTouchAction: string | null;
}
}
export interface Options {
dotSize?: number | (() => number);
minWidth?: number;
maxWidth?: number;
export declare type SignatureEvent = MouseEvent | Touch | PointerEvent;
export interface FromDataOptions {
clear?: boolean;
}
export interface PointGroupOptions {
dotSize: number;
minWidth: number;
maxWidth: number;
penColor: string;
}
export interface Options extends Partial<PointGroupOptions> {
minDistance?: number;
velocityFilterWeight?: number;
backgroundColor?: string;
penColor?: string;
throttle?: number;
velocityFilterWeight?: number;
onBegin?: (event: MouseEvent | Touch) => void;
onEnd?: (event: MouseEvent | Touch) => void;
}
export interface PointGroup {
color: string;
export interface PointGroup extends PointGroupOptions {
points: BasicPoint[];
}
export default class SignaturePad {
export default class SignaturePad extends EventTarget {
private canvas;
private options;
dotSize: number | (() => number);
dotSize: number;
minWidth: number;
maxWidth: number;
penColor: string;
minDistance: number;
velocityFilterWeight: number;
backgroundColor: string;
penColor: string;
throttle: number;
velocityFilterWeight: number;
onBegin?: (event: MouseEvent | Touch) => void;
onEnd?: (event: MouseEvent | Touch) => void;
private _ctx;
private _mouseButtonDown;
private _drawningStroke;
private _isEmpty;

@@ -62,3 +63,5 @@ private _lastPoints;

height?: number;
}, callback?: (error?: string | Event) => void): void;
xOffset?: number;
yOffset?: number;
}): Promise<void>;
toDataURL(type?: string, encoderOptions?: number): string;

@@ -68,3 +71,3 @@ on(): void;

isEmpty(): boolean;
fromData(pointGroups: PointGroup[]): void;
fromData(pointGroups: PointGroup[], { clear }?: FromDataOptions): void;
toData(): PointGroup[];

@@ -77,2 +80,5 @@ private _handleMouseDown;

private _handleTouchEnd;
private _handlePointerStart;
private _handlePointerMove;
private _handlePointerEnd;
private _strokeBegin;

@@ -79,0 +85,0 @@ private _strokeUpdate;

/*!
* Signature Pad v3.0.0-beta.4 | https://github.com/szimek/signature_pad
* (c) 2020 Szymon Nowak | Released under the MIT license
* Signature Pad v4.0.0 | https://github.com/szimek/signature_pad
* (c) 2021 Szymon Nowak | Released under the MIT license
*/

@@ -10,26 +10,32 @@

(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SignaturePad = factory());
}(this, (function () { 'use strict';
})(this, (function () { 'use strict';
var Point = (function () {
function Point(x, y, time) {
this.x = x;
this.y = y;
class Point {
constructor(x, y, pressure, time) {
if (isNaN(x) || isNaN(y)) {
throw new Error(`Point is invalid: (${x}, ${y})`);
}
this.x = +x;
this.y = +y;
this.pressure = pressure || 0;
this.time = time || Date.now();
}
Point.prototype.distanceTo = function (start) {
distanceTo(start) {
return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
};
Point.prototype.equals = function (other) {
return this.x === other.x && this.y === other.y && this.time === other.time;
};
Point.prototype.velocityFrom = function (start) {
}
equals(other) {
return (this.x === other.x &&
this.y === other.y &&
this.pressure === other.pressure &&
this.time === other.time);
}
velocityFrom(start) {
return this.time !== start.time
? this.distanceTo(start) / (this.time - start.time)
: 0;
};
return Point;
}());
}
}
var Bezier = (function () {
function Bezier(startPoint, control2, control1, endPoint, startWidth, endWidth) {
class Bezier {
constructor(startPoint, control2, control1, endPoint, startWidth, endWidth) {
this.startPoint = startPoint;

@@ -42,39 +48,39 @@ this.control2 = control2;

}
Bezier.fromPoints = function (points, widths) {
var c2 = this.calculateControlPoints(points[0], points[1], points[2]).c2;
var c3 = this.calculateControlPoints(points[1], points[2], points[3]).c1;
static fromPoints(points, widths) {
const c2 = this.calculateControlPoints(points[0], points[1], points[2]).c2;
const c3 = this.calculateControlPoints(points[1], points[2], points[3]).c1;
return new Bezier(points[1], c2, c3, points[2], widths.start, widths.end);
};
Bezier.calculateControlPoints = function (s1, s2, s3) {
var dx1 = s1.x - s2.x;
var dy1 = s1.y - s2.y;
var dx2 = s2.x - s3.x;
var dy2 = s2.y - s3.y;
var m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
var m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };
var l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
var l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
var dxm = m1.x - m2.x;
var dym = m1.y - m2.y;
var k = l2 / (l1 + l2);
var cm = { x: m2.x + dxm * k, y: m2.y + dym * k };
var tx = s2.x - cm.x;
var ty = s2.y - cm.y;
}
static calculateControlPoints(s1, s2, s3) {
const dx1 = s1.x - s2.x;
const dy1 = s1.y - s2.y;
const dx2 = s2.x - s3.x;
const dy2 = s2.y - s3.y;
const m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 };
const m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 };
const l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
const l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
const dxm = m1.x - m2.x;
const dym = m1.y - m2.y;
const k = l2 / (l1 + l2);
const cm = { x: m2.x + dxm * k, y: m2.y + dym * k };
const tx = s2.x - cm.x;
const ty = s2.y - cm.y;
return {
c1: new Point(m1.x + tx, m1.y + ty),
c2: new Point(m2.x + tx, m2.y + ty)
c2: new Point(m2.x + tx, m2.y + ty),
};
};
Bezier.prototype.length = function () {
var steps = 10;
var length = 0;
var px;
var py;
for (var i = 0; i <= steps; i += 1) {
var t = i / steps;
var cx = this.point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
var cy = this.point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
}
length() {
const steps = 10;
let length = 0;
let px;
let py;
for (let i = 0; i <= steps; i += 1) {
const t = i / steps;
const cx = this.point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
const cy = this.point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
if (i > 0) {
var xdiff = cx - px;
var ydiff = cy - py;
const xdiff = cx - px;
const ydiff = cy - py;
length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);

@@ -86,4 +92,4 @@ }

return length;
};
Bezier.prototype.point = function (t, start, c1, c2, end) {
}
point(t, start, c1, c2, end) {
return (start * (1.0 - t) * (1.0 - t) * (1.0 - t))

@@ -93,14 +99,12 @@ + (3.0 * c1 * (1.0 - t) * (1.0 - t) * t)

+ (end * t * t * t);
};
return Bezier;
}());
}
}
function throttle(fn, wait) {
if (wait === void 0) { wait = 250; }
var previous = 0;
var timeout = null;
var result;
var storedContext;
var storedArgs;
var later = function () {
function throttle(fn, wait = 250) {
let previous = 0;
let timeout = null;
let result;
let storedContext;
let storedArgs;
const later = () => {
previous = Date.now();

@@ -114,9 +118,5 @@ timeout = null;

};
return function wrapper() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var now = Date.now();
var remaining = wait - (now - previous);
return function wrapper(...args) {
const now = Date.now();
const remaining = wait - (now - previous);
storedContext = this;

@@ -143,45 +143,63 @@ storedArgs = args;

var SignaturePad = (function () {
function SignaturePad(canvas, options) {
var _this = this;
if (options === void 0) { options = {}; }
class SignaturePad extends EventTarget {
constructor(canvas, options = {}) {
super();
this.canvas = canvas;
this.options = options;
this._handleMouseDown = function (event) {
if (event.which === 1) {
_this._mouseButtonDown = true;
_this._strokeBegin(event);
this._handleMouseDown = (event) => {
if (event.buttons === 1) {
this._drawningStroke = true;
this._strokeBegin(event);
}
};
this._handleMouseMove = function (event) {
if (_this._mouseButtonDown) {
_this._strokeMoveUpdate(event);
this._handleMouseMove = (event) => {
if (this._drawningStroke) {
this._strokeMoveUpdate(event);
}
};
this._handleMouseUp = function (event) {
if (event.which === 1 && _this._mouseButtonDown) {
_this._mouseButtonDown = false;
_this._strokeEnd(event);
this._handleMouseUp = (event) => {
if (event.buttons === 1 && this._drawningStroke) {
this._drawningStroke = false;
this._strokeEnd(event);
}
};
this._handleTouchStart = function (event) {
this._handleTouchStart = (event) => {
event.preventDefault();
if (event.targetTouches.length === 1) {
var touch = event.changedTouches[0];
_this._strokeBegin(touch);
const touch = event.changedTouches[0];
this._strokeBegin(touch);
}
};
this._handleTouchMove = function (event) {
this._handleTouchMove = (event) => {
event.preventDefault();
var touch = event.targetTouches[0];
_this._strokeMoveUpdate(touch);
const touch = event.targetTouches[0];
this._strokeMoveUpdate(touch);
};
this._handleTouchEnd = function (event) {
var wasCanvasTouched = event.target === _this.canvas;
this._handleTouchEnd = (event) => {
const wasCanvasTouched = event.target === this.canvas;
if (wasCanvasTouched) {
event.preventDefault();
var touch = event.changedTouches[0];
_this._strokeEnd(touch);
const touch = event.changedTouches[0];
this._strokeEnd(touch);
}
};
this._handlePointerStart = (event) => {
this._drawningStroke = true;
event.preventDefault();
this._strokeBegin(event);
};
this._handlePointerMove = (event) => {
if (this._drawningStroke) {
event.preventDefault();
this._strokeMoveUpdate(event);
}
};
this._handlePointerEnd = (event) => {
this._drawningStroke = false;
const wasCanvasTouched = event.target === this.canvas;
if (wasCanvasTouched) {
event.preventDefault();
this._strokeEnd(event);
}
};
this.velocityFilterWeight = options.velocityFilterWeight || 0.7;

@@ -191,14 +209,6 @@ this.minWidth = options.minWidth || 0.5;

this.throttle = ('throttle' in options ? options.throttle : 16);
this.minDistance = ('minDistance' in options
? options.minDistance
: 5);
this.dotSize =
options.dotSize ||
function dotSize() {
return (this.minWidth + this.maxWidth) / 2;
};
this.minDistance = ('minDistance' in options ? options.minDistance : 5);
this.dotSize = options.dotSize || 0;
this.penColor = options.penColor || 'black';
this.backgroundColor = options.backgroundColor || 'rgba(0,0,0,0)';
this.onBegin = options.onBegin;
this.onEnd = options.onEnd;
this._strokeMoveUpdate = this.throttle

@@ -211,4 +221,4 @@ ? throttle(SignaturePad.prototype._strokeUpdate, this.throttle)

}
SignaturePad.prototype.clear = function () {
var _a = this, ctx = _a._ctx, canvas = _a.canvas;
clear() {
const { _ctx: ctx, canvas } = this;
ctx.fillStyle = this.backgroundColor;

@@ -220,27 +230,25 @@ ctx.clearRect(0, 0, canvas.width, canvas.height);

this._isEmpty = true;
};
SignaturePad.prototype.fromDataURL = function (dataUrl, options, callback) {
var _this = this;
if (options === void 0) { options = {}; }
var image = new Image();
var ratio = options.ratio || window.devicePixelRatio || 1;
var width = options.width || this.canvas.width / ratio;
var height = options.height || this.canvas.height / ratio;
this._reset();
image.onload = function () {
_this._ctx.drawImage(image, 0, 0, width, height);
if (callback) {
callback();
}
};
image.onerror = function (error) {
if (callback) {
callback(error);
}
};
image.src = dataUrl;
this._isEmpty = false;
};
SignaturePad.prototype.toDataURL = function (type, encoderOptions) {
if (type === void 0) { type = 'image/png'; }
}
fromDataURL(dataUrl, options = {}) {
return new Promise((resolve, reject) => {
const image = new Image();
const ratio = options.ratio || window.devicePixelRatio || 1;
const width = options.width || this.canvas.width / ratio;
const height = options.height || this.canvas.height / ratio;
const xOffset = options.xOffset || 0;
const yOffset = options.yOffset || 0;
this._reset();
image.onload = () => {
this._ctx.drawImage(image, xOffset, yOffset, width, height);
resolve();
};
image.onerror = (error) => {
reject(error);
};
image.crossOrigin = 'anonymous';
image.src = dataUrl;
this._isEmpty = false;
});
}
toDataURL(type = 'image/png', encoderOptions) {
switch (type) {

@@ -252,4 +260,4 @@ case 'image/svg+xml':

}
};
SignaturePad.prototype.on = function () {
}
on() {
this.canvas.style.touchAction = 'none';

@@ -266,9 +274,9 @@ this.canvas.style.msTouchAction = 'none';

}
};
SignaturePad.prototype.off = function () {
}
off() {
this.canvas.style.touchAction = 'auto';
this.canvas.style.msTouchAction = 'auto';
this.canvas.removeEventListener('pointerdown', this._handleMouseDown);
this.canvas.removeEventListener('pointermove', this._handleMouseMove);
document.removeEventListener('pointerup', this._handleMouseUp);
this.canvas.removeEventListener('pointerdown', this._handlePointerStart);
this.canvas.removeEventListener('pointermove', this._handlePointerMove);
document.removeEventListener('pointerup', this._handlePointerEnd);
this.canvas.removeEventListener('mousedown', this._handleMouseDown);

@@ -280,34 +288,30 @@ this.canvas.removeEventListener('mousemove', this._handleMouseMove);

this.canvas.removeEventListener('touchend', this._handleTouchEnd);
};
SignaturePad.prototype.isEmpty = function () {
}
isEmpty() {
return this._isEmpty;
};
SignaturePad.prototype.fromData = function (pointGroups) {
var _this = this;
this.clear();
this._fromData(pointGroups, function (_a) {
var color = _a.color, curve = _a.curve;
return _this._drawCurve({ color: color, curve: curve });
}, function (_a) {
var color = _a.color, point = _a.point;
return _this._drawDot({ color: color, point: point });
});
this._data = pointGroups;
};
SignaturePad.prototype.toData = function () {
}
fromData(pointGroups, { clear = true } = {}) {
if (clear) {
this.clear();
}
this._fromData(pointGroups, this._drawCurve.bind(this), this._drawDot.bind(this));
this._data = clear ? pointGroups : this._data.concat(pointGroups);
}
toData() {
return this._data;
};
SignaturePad.prototype._strokeBegin = function (event) {
var newPointGroup = {
color: this.penColor,
points: []
}
_strokeBegin(event) {
this.dispatchEvent(new CustomEvent('beginStroke', { detail: event }));
const newPointGroup = {
dotSize: this.dotSize,
minWidth: this.minWidth,
maxWidth: this.maxWidth,
penColor: this.penColor,
points: [],
};
if (typeof this.onBegin === 'function') {
this.onBegin(event);
}
this._data.push(newPointGroup);
this._reset();
this._strokeUpdate(event);
};
SignaturePad.prototype._strokeUpdate = function (event) {
}
_strokeUpdate(event) {
if (this._data.length === 0) {

@@ -317,19 +321,35 @@ this._strokeBegin(event);

}
var x = event.clientX;
var y = event.clientY;
var point = this._createPoint(x, y);
var lastPointGroup = this._data[this._data.length - 1];
var lastPoints = lastPointGroup.points;
var lastPoint = lastPoints.length > 0 && lastPoints[lastPoints.length - 1];
var isLastPointTooClose = lastPoint
this.dispatchEvent(new CustomEvent('beforeUpdateStroke', { detail: event }));
const x = event.clientX;
const y = event.clientY;
const pressure = event.pressure !== undefined
? event.pressure
: event.force !== undefined
? event.force
: 0;
const point = this._createPoint(x, y, pressure);
const lastPointGroup = this._data[this._data.length - 1];
const lastPoints = lastPointGroup.points;
const lastPoint = lastPoints.length > 0 && lastPoints[lastPoints.length - 1];
const isLastPointTooClose = lastPoint
? point.distanceTo(lastPoint) <= this.minDistance
: false;
var color = lastPointGroup.color;
const { penColor, dotSize, minWidth, maxWidth } = lastPointGroup;
if (!lastPoint || !(lastPoint && isLastPointTooClose)) {
var curve = this._addPoint(point);
const curve = this._addPoint(point);
if (!lastPoint) {
this._drawDot({ color: color, point: point });
this._drawDot(point, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}
else if (curve) {
this._drawCurve({ color: color, curve: curve });
this._drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -339,30 +359,30 @@ lastPoints.push({

x: point.x,
y: point.y
y: point.y,
pressure: point.pressure,
});
}
};
SignaturePad.prototype._strokeEnd = function (event) {
this.dispatchEvent(new CustomEvent('afterUpdateStroke', { detail: event }));
}
_strokeEnd(event) {
this._strokeUpdate(event);
if (typeof this.onEnd === 'function') {
this.onEnd(event);
}
};
SignaturePad.prototype._handlePointerEvents = function () {
this._mouseButtonDown = false;
this.canvas.addEventListener('pointerdown', this._handleMouseDown);
this.canvas.addEventListener('pointermove', this._handleMouseMove);
document.addEventListener('pointerup', this._handleMouseUp);
};
SignaturePad.prototype._handleMouseEvents = function () {
this._mouseButtonDown = false;
this.dispatchEvent(new CustomEvent('endStroke', { detail: event }));
}
_handlePointerEvents() {
this._drawningStroke = false;
this.canvas.addEventListener('pointerdown', this._handlePointerStart);
this.canvas.addEventListener('pointermove', this._handlePointerMove);
document.addEventListener('pointerup', this._handlePointerEnd);
}
_handleMouseEvents() {
this._drawningStroke = false;
this.canvas.addEventListener('mousedown', this._handleMouseDown);
this.canvas.addEventListener('mousemove', this._handleMouseMove);
document.addEventListener('mouseup', this._handleMouseUp);
};
SignaturePad.prototype._handleTouchEvents = function () {
}
_handleTouchEvents() {
this.canvas.addEventListener('touchstart', this._handleTouchStart);
this.canvas.addEventListener('touchmove', this._handleTouchMove);
this.canvas.addEventListener('touchend', this._handleTouchEnd);
};
SignaturePad.prototype._reset = function () {
}
_reset() {
this._lastPoints = [];

@@ -372,9 +392,9 @@ this._lastVelocity = 0;

this._ctx.fillStyle = this.penColor;
};
SignaturePad.prototype._createPoint = function (x, y) {
var rect = this.canvas.getBoundingClientRect();
return new Point(x - rect.left, y - rect.top, new Date().getTime());
};
SignaturePad.prototype._addPoint = function (point) {
var _lastPoints = this._lastPoints;
}
_createPoint(x, y, pressure) {
const rect = this.canvas.getBoundingClientRect();
return new Point(x - rect.left, y - rect.top, pressure, new Date().getTime());
}
_addPoint(point) {
const { _lastPoints } = this;
_lastPoints.push(point);

@@ -385,4 +405,4 @@ if (_lastPoints.length > 2) {

}
var widths = this._calculateCurveWidths(_lastPoints[1], _lastPoints[2]);
var curve = Bezier.fromPoints(_lastPoints, widths);
const widths = this._calculateCurveWidths(_lastPoints[1], _lastPoints[2]);
const curve = Bezier.fromPoints(_lastPoints, widths);
_lastPoints.shift();

@@ -392,10 +412,10 @@ return curve;

return null;
};
SignaturePad.prototype._calculateCurveWidths = function (startPoint, endPoint) {
var velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) +
}
_calculateCurveWidths(startPoint, endPoint) {
const velocity = this.velocityFilterWeight * endPoint.velocityFrom(startPoint) +
(1 - this.velocityFilterWeight) * this._lastVelocity;
var newWidth = this._strokeWidth(velocity);
var widths = {
const newWidth = this._strokeWidth(velocity);
const widths = {
end: newWidth,
start: this._lastWidth
start: this._lastWidth,
};

@@ -405,35 +425,34 @@ this._lastVelocity = velocity;

return widths;
};
SignaturePad.prototype._strokeWidth = function (velocity) {
}
_strokeWidth(velocity) {
return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
};
SignaturePad.prototype._drawCurveSegment = function (x, y, width) {
var ctx = this._ctx;
}
_drawCurveSegment(x, y, width) {
const ctx = this._ctx;
ctx.moveTo(x, y);
ctx.arc(x, y, width, 0, 2 * Math.PI, false);
this._isEmpty = false;
};
SignaturePad.prototype._drawCurve = function (_a) {
var color = _a.color, curve = _a.curve;
var ctx = this._ctx;
var widthDelta = curve.endWidth - curve.startWidth;
var drawSteps = Math.floor(curve.length()) * 2;
}
_drawCurve(curve, options) {
const ctx = this._ctx;
const widthDelta = curve.endWidth - curve.startWidth;
const drawSteps = Math.ceil(curve.length()) * 2;
ctx.beginPath();
ctx.fillStyle = color;
for (var i = 0; i < drawSteps; i += 1) {
var t = i / drawSteps;
var tt = t * t;
var ttt = tt * t;
var u = 1 - t;
var uu = u * u;
var uuu = uu * u;
var x = uuu * curve.startPoint.x;
ctx.fillStyle = options.penColor;
for (let i = 0; i < drawSteps; i += 1) {
const t = i / drawSteps;
const tt = t * t;
const ttt = tt * t;
const u = 1 - t;
const uu = u * u;
const uuu = uu * u;
let x = uuu * curve.startPoint.x;
x += 3 * uu * t * curve.control1.x;
x += 3 * u * tt * curve.control2.x;
x += ttt * curve.endPoint.x;
var y = uuu * curve.startPoint.y;
let y = uuu * curve.startPoint.y;
y += 3 * uu * t * curve.control1.y;
y += 3 * u * tt * curve.control2.y;
y += ttt * curve.endPoint.y;
var width = Math.min(curve.startWidth + ttt * widthDelta, this.maxWidth);
const width = Math.min(curve.startWidth + ttt * widthDelta, options.maxWidth);
this._drawCurveSegment(x, y, width);

@@ -443,28 +462,33 @@ }

ctx.fill();
};
SignaturePad.prototype._drawDot = function (_a) {
var color = _a.color, point = _a.point;
var ctx = this._ctx;
var width = typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;
}
_drawDot(point, options) {
const ctx = this._ctx;
const width = options.dotSize > 0
? options.dotSize
: (options.minWidth + options.maxWidth) / 2;
ctx.beginPath();
this._drawCurveSegment(point.x, point.y, width);
ctx.closePath();
ctx.fillStyle = color;
ctx.fillStyle = options.penColor;
ctx.fill();
};
SignaturePad.prototype._fromData = function (pointGroups, drawCurve, drawDot) {
for (var _i = 0, pointGroups_1 = pointGroups; _i < pointGroups_1.length; _i++) {
var group = pointGroups_1[_i];
var color = group.color, points = group.points;
}
_fromData(pointGroups, drawCurve, drawDot) {
for (const group of pointGroups) {
const { penColor, dotSize, minWidth, maxWidth, points } = group;
if (points.length > 1) {
for (var j = 0; j < points.length; j += 1) {
var basicPoint = points[j];
var point = new Point(basicPoint.x, basicPoint.y, basicPoint.time);
this.penColor = color;
for (let j = 0; j < points.length; j += 1) {
const basicPoint = points[j];
const point = new Point(basicPoint.x, basicPoint.y, basicPoint.pressure, basicPoint.time);
this.penColor = penColor;
if (j === 0) {
this._reset();
}
var curve = this._addPoint(point);
const curve = this._addPoint(point);
if (curve) {
drawCurve({ color: color, curve: curve });
drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -475,23 +499,23 @@ }

this._reset();
drawDot({
color: color,
point: points[0]
drawDot(points[0], {
penColor,
dotSize,
minWidth,
maxWidth,
});
}
}
};
SignaturePad.prototype._toSVG = function () {
var _this = this;
var pointGroups = this._data;
var ratio = Math.max(window.devicePixelRatio || 1, 1);
var minX = 0;
var minY = 0;
var maxX = this.canvas.width / ratio;
var maxY = this.canvas.height / ratio;
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
}
_toSVG() {
const pointGroups = this._data;
const ratio = Math.max(window.devicePixelRatio || 1, 1);
const minX = 0;
const minY = 0;
const maxX = this.canvas.width / ratio;
const maxY = this.canvas.height / ratio;
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('width', this.canvas.width.toString());
svg.setAttribute('height', this.canvas.height.toString());
this._fromData(pointGroups, function (_a) {
var color = _a.color, curve = _a.curve;
var path = document.createElement('path');
this._fromData(pointGroups, (curve, { penColor }) => {
const path = document.createElement('path');
if (!isNaN(curve.control1.x) &&

@@ -501,9 +525,9 @@ !isNaN(curve.control1.y) &&

!isNaN(curve.control2.y)) {
var attr = "M " + curve.startPoint.x.toFixed(3) + "," + curve.startPoint.y.toFixed(3) + " " +
("C " + curve.control1.x.toFixed(3) + "," + curve.control1.y.toFixed(3) + " ") +
(curve.control2.x.toFixed(3) + "," + curve.control2.y.toFixed(3) + " ") +
(curve.endPoint.x.toFixed(3) + "," + curve.endPoint.y.toFixed(3));
const attr = `M ${curve.startPoint.x.toFixed(3)},${curve.startPoint.y.toFixed(3)} ` +
`C ${curve.control1.x.toFixed(3)},${curve.control1.y.toFixed(3)} ` +
`${curve.control2.x.toFixed(3)},${curve.control2.y.toFixed(3)} ` +
`${curve.endPoint.x.toFixed(3)},${curve.endPoint.y.toFixed(3)}`;
path.setAttribute('d', attr);
path.setAttribute('stroke-width', (curve.endWidth * 2.25).toFixed(3));
path.setAttribute('stroke', color);
path.setAttribute('stroke', penColor);
path.setAttribute('fill', 'none');

@@ -513,26 +537,25 @@ path.setAttribute('stroke-linecap', 'round');

}
}, function (_a) {
var color = _a.color, point = _a.point;
var circle = document.createElement('circle');
var dotSize = typeof _this.dotSize === 'function' ? _this.dotSize() : _this.dotSize;
circle.setAttribute('r', dotSize.toString());
}, (point, { penColor, dotSize, minWidth, maxWidth }) => {
const circle = document.createElement('circle');
const size = dotSize > 0 ? dotSize : (minWidth + maxWidth) / 2;
circle.setAttribute('r', size.toString());
circle.setAttribute('cx', point.x.toString());
circle.setAttribute('cy', point.y.toString());
circle.setAttribute('fill', color);
circle.setAttribute('fill', penColor);
svg.appendChild(circle);
});
var prefix = 'data:image/svg+xml;base64,';
var header = '<svg' +
const prefix = 'data:image/svg+xml;base64,';
const header = '<svg' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink"' +
(" viewBox=\"" + minX + " " + minY + " " + maxX + " " + maxY + "\"") +
(" width=\"" + maxX + "\"") +
(" height=\"" + maxY + "\"") +
` viewBox="${minX} ${minY} ${this.canvas.width} ${this.canvas.height}"` +
` width="${maxX}"` +
` height="${maxY}"` +
'>';
var body = svg.innerHTML;
let body = svg.innerHTML;
if (body === undefined) {
var dummy = document.createElement('dummy');
var nodes = svg.childNodes;
const dummy = document.createElement('dummy');
const nodes = svg.childNodes;
dummy.innerHTML = '';
for (var i = 0; i < nodes.length; i += 1) {
for (let i = 0; i < nodes.length; i += 1) {
dummy.appendChild(nodes[i].cloneNode(true));

@@ -542,12 +565,11 @@ }

}
var footer = '</svg>';
var data = header + body + footer;
const footer = '</svg>';
const data = header + body + footer;
return prefix + btoa(data);
};
return SignaturePad;
}());
}
}
return SignaturePad;
})));
}));
//# sourceMappingURL=signature_pad.umd.js.map
{
"name": "signature_pad",
"description": "Library for drawing smooth signatures.",
"version": "3.0.0-beta.4",
"version": "4.0.0",
"homepage": "https://github.com/szimek/signature_pad",

@@ -19,5 +19,5 @@ "author": {

"clean": "yarn run del dist",
"emit-types": "mkdir -p dist/types && yarn run tsc src/signature_pad.ts --lib DOM,ES2015 --declaration --declarationDir dist/types --emitDeclarationOnly",
"format": "prettier --write '{src,tests}/**/*.{js,ts}'",
"lint": "eslint '{src,tests}/**/*.ts'",
"emit-types": "yarn run del dist/types && yarn run tsc src/signature_pad.ts --lib DOM,ES2015 --declaration --declarationDir dist/types --emitDeclarationOnly",
"format": "prettier --write {src,tests}/**/*.{js,ts}",
"lint": "eslint {src,tests}/**/*.ts",
"prepublishOnly": "yarn run build",

@@ -27,3 +27,4 @@ "serve": "serve -l 9000 docs",

"test": "jest --coverage",
"update-docs": "cp dist/signature_pad.umd.js docs/js/"
"update-docs": "yarn run cp-cli dist/signature_pad.umd.js docs/js/signature_pad.umd.js",
"prepare": "husky install"
},

@@ -40,33 +41,26 @@ "repository": {

"devDependencies": {
"@rollup/plugin-typescript": "^6.0.0",
"@types/jest": "^26.0.14",
"@types/node": "^14.11.1",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"canvas": "^2.6.1",
"del": "^5.1.0",
"del-cli": "^3.0.1",
"eslint": "^7.9.0",
"eslint-config-prettier": "^6.11.0",
"husky": "^4.3.0",
"jest": "^26.4.2",
"lint-staged": "^10.4.0",
"prettier": "^2.1.2",
"rollup": "^2.27.1",
"@rollup/plugin-typescript": "^8.3.0",
"@types/jest": "^27.0.3",
"@types/node": "^16.11.9",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"@typescript-eslint/parser": "^5.4.0",
"canvas": "^2.8.0",
"cp-cli": "^2.0.0",
"del": "^6.0.0",
"del-cli": "^4.0.1",
"eslint": "^8.3.0",
"eslint-config-prettier": "^8.3.0",
"husky": "^7.0.4",
"jest": "^27.3.1",
"lint-staged": "^12.1.2",
"prettier": "^2.4.1",
"rollup": "^2.60.1",
"rollup-plugin-terser": "^7.0.2",
"serve": "^11.3.2",
"ts-jest": "^26.3.0",
"tslib": "^2.0.1",
"typescript": "^4.0.3"
"serve": "^13.0.2",
"ts-jest": "^27.0.7",
"tslib": "^2.3.1",
"typescript": "^4.5.2"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.ts": [
"yarn run prettier",
"yarn run lint"
]
"*.ts": "prettier --write"
},

@@ -78,2 +72,3 @@ "jest": {

],
"testEnvironment": "jsdom",
"testEnvironmentOptions": {

@@ -80,0 +75,0 @@ "resources": "usable"

# Signature Pad [![npm](https://badge.fury.io/js/signature_pad.svg)](https://www.npmjs.com/package/signature_pad) [![Build Status](https://travis-ci.org/szimek/signature_pad.svg?branch=master)](https://travis-ci.org/szimek/signature_pad) [![Code Climate](https://codeclimate.com/github/szimek/signature_pad.png)](https://codeclimate.com/github/szimek/signature_pad)
Signature Pad is a JavaScript library for drawing smooth signatures. It's HTML5 canvas based and uses variable width Bézier curve interpolation based on [Smoother Signatures](http://corner.squareup.com/2012/07/smoother-signatures.html) post by [Square](https://squareup.com).
Signature Pad is a JavaScript library for drawing smooth signatures. It's HTML5 canvas based and uses variable width Bézier curve interpolation based on [Smoother Signatures](https://developer.squareup.com/blog/smoother-signatures/) post by [Square](https://squareup.com).
It works in all modern desktop and mobile browsers and doesn't depend on any external libraries.

@@ -8,2 +8,7 @@

## Looking for a maintainer
I wrote this library as it solved a problem I had at the time. Unfortunately, I no longer have time or motivation to work on this library anymore.
Please reach out to me if you'd like to help out and eventually maintain this project.
## Demo

@@ -37,5 +42,5 @@ [Demo](http://szimek.github.io/signature_pad) works in desktop and mobile browsers. You can check out its [source code](https://github.com/szimek/signature_pad/blob/gh-pages/js/app.js) for some tips on how to handle window resize and high DPI screens. You can also find more about the latter in [HTML5 Rocks tutorial](http://www.html5rocks.com/en/tutorials/canvas/hidpi).

``` javascript
var canvas = document.querySelector("canvas");
const canvas = document.querySelector("canvas");
var signaturePad = new SignaturePad(canvas);
const signaturePad = new SignaturePad(canvas);

@@ -57,2 +62,5 @@ // Returns signature image as data URL (see https://mdn.io/todataurl for the list of possible parameters)

// Draws signature image from an array of point groups, without clearing your existing image (clear defaults to true if not provided)
signaturePad.fromData(data, { clear: false });
// Clears the canvas

@@ -89,6 +97,2 @@ signaturePad.clear();

<dd>(float) Weight used to modify new velocity based on the previous velocity. Defaults to <code>0.7</code>.</dd>
<dt>onBegin</dt>
<dd>(function) Callback when stroke begin.</dd>
<dt>onEnd</dt>
<dd>(function) Callback when stroke end.</dd>
</dl>

@@ -98,3 +102,3 @@

```javascript
var signaturePad = new SignaturePad(canvas, {
const signaturePad = new SignaturePad(canvas, {
minWidth: 5,

@@ -107,3 +111,3 @@ maxWidth: 10,

```javascript
var signaturePad = new SignaturePad(canvas);
const signaturePad = new SignaturePad(canvas);
signaturePad.minWidth = 5;

@@ -114,3 +118,22 @@ signaturePad.maxWidth = 10;

### Events
<dl>
<dt>beginStroke</dt>
<dd>Triggered before stroke begins.</dd>
<dt>endStroke</dt>
<dd>Triggered after stroke ends.</dd>
<dt>beforeUpdateStroke</dt>
<dd>Triggered before stroke update.</dd>
<dt>afterUpdateStroke</dt>
<dd>Triggered after stroke update.</dd>
</dl>
You can add listeners to events with [`.addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener):
```javascript
const signaturePad = new SignaturePad(canvas);
signaturePad.addEventListener("beginStroke", () => {
console.log("Signature started");
}, { once: true });
```
### Tips and tricks

@@ -121,3 +144,3 @@ #### Handling high DPI screens

function resizeCanvas() {
var ratio = Math.max(window.devicePixelRatio || 1, 1);
const ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;

@@ -175,3 +198,3 @@ canvas.height = canvas.offsetHeight * ratio;

var dataUri = "data:image/png;base64,iVBORw0K...";
var encodedImage = dataUri.Split(",")[1];
var encodedImage = dataUri.Split(',')[1];
var decodedImage = Convert.FromBase64String(encodedImage);

@@ -178,0 +201,0 @@ System.IO.File.WriteAllBytes("signature.png", decodedImage);

@@ -5,2 +5,3 @@ // Interface for point data structure used e.g. in SignaturePad#fromData method

y: number;
pressure: number;
time: number;

@@ -10,5 +11,14 @@ }

export class Point implements BasicPoint {
public x: number;
public y: number;
public pressure: number;
public time: number;
constructor(public x: number, public y: number, time?: number) {
constructor(x: number, y: number, pressure?: number, time?: number) {
if (isNaN(x) || isNaN(y)) {
throw new Error(`Point is invalid: (${x}, ${y})`);
}
this.x = +x;
this.y = +y;
this.pressure = pressure || 0;
this.time = time || Date.now();

@@ -24,3 +34,8 @@ }

public equals(other: BasicPoint): boolean {
return this.x === other.x && this.y === other.y && this.time === other.time;
return (
this.x === other.x &&
this.y === other.y &&
this.pressure === other.pressure &&
this.time === other.time
);
}

@@ -27,0 +42,0 @@

@@ -6,3 +6,3 @@ /**

* Implementation of interpolation using cubic Bézier curves is taken from:
* http://www.benknowscode.com/2012/09/path-interpolation-using-cubic-bezier_9742.html
* https://web.archive.org/web/20160323213433/http://www.benknowscode.com/2012/09/path-interpolation-using-cubic-bezier_9742.html
*

@@ -19,36 +19,40 @@ * Algorithm for approximated length of a Bézier curve is taken from:

interface CSSStyleDeclaration {
msTouchAction: string;
msTouchAction: string | null;
}
}
export interface Options {
dotSize?: number | (() => number);
minWidth?: number;
maxWidth?: number;
export type SignatureEvent = MouseEvent | Touch | PointerEvent;
export interface FromDataOptions {
clear?: boolean;
}
export interface PointGroupOptions {
dotSize: number;
minWidth: number;
maxWidth: number;
penColor: string;
}
export interface Options extends Partial<PointGroupOptions> {
minDistance?: number;
velocityFilterWeight?: number;
backgroundColor?: string;
penColor?: string;
throttle?: number;
velocityFilterWeight?: number;
onBegin?: (event: MouseEvent | Touch) => void;
onEnd?: (event: MouseEvent | Touch) => void;
}
export interface PointGroup {
color: string;
export interface PointGroup extends PointGroupOptions {
points: BasicPoint[];
}
export default class SignaturePad {
export default class SignaturePad extends EventTarget {
// Public stuff
public dotSize: number | (() => number);
public dotSize: number;
public minWidth: number;
public maxWidth: number;
public penColor: string;
public minDistance: number;
public velocityFilterWeight: number;
public backgroundColor: string;
public penColor: string;
public throttle: number;
public velocityFilterWeight: number;
public onBegin?: (event: MouseEvent | Touch) => void;
public onEnd?: (event: MouseEvent | Touch) => void;

@@ -58,3 +62,3 @@ // Private stuff

private _ctx: CanvasRenderingContext2D;
private _mouseButtonDown: boolean;
private _drawningStroke: boolean;
private _isEmpty: boolean;

@@ -65,3 +69,3 @@ private _lastPoints: Point[]; // Stores up to 4 most recent points; used to generate a new curve

private _lastWidth: number;
private _strokeMoveUpdate: (event: MouseEvent | Touch) => void;
private _strokeMoveUpdate: (event: SignatureEvent) => void;
/* tslint:enable: variable-name */

@@ -73,2 +77,3 @@

) {
super();
this.velocityFilterWeight = options.velocityFilterWeight || 0.7;

@@ -78,14 +83,8 @@ this.minWidth = options.minWidth || 0.5;

this.throttle = ('throttle' in options ? options.throttle : 16) as number; // in milisecondss
this.minDistance = ('minDistance' in options
? options.minDistance
: 5) as number; // in pixels
this.dotSize =
options.dotSize ||
function dotSize(this: SignaturePad): number {
return (this.minWidth + this.maxWidth) / 2;
};
this.minDistance = (
'minDistance' in options ? options.minDistance : 5
) as number; // in pixels
this.dotSize = options.dotSize || 0;
this.penColor = options.penColor || 'black';
this.backgroundColor = options.backgroundColor || 'rgba(0,0,0,0)';
this.onBegin = options.onBegin;
this.onEnd = options.onEnd;

@@ -118,26 +117,32 @@ this._strokeMoveUpdate = this.throttle

dataUrl: string,
options: { ratio?: number; width?: number; height?: number } = {},
callback?: (error?: string | Event) => void,
): void {
const image = new Image();
const ratio = options.ratio || window.devicePixelRatio || 1;
const width = options.width || this.canvas.width / ratio;
const height = options.height || this.canvas.height / ratio;
options: {
ratio?: number;
width?: number;
height?: number;
xOffset?: number;
yOffset?: number;
} = {},
): Promise<void> {
return new Promise((resolve, reject) => {
const image = new Image();
const ratio = options.ratio || window.devicePixelRatio || 1;
const width = options.width || this.canvas.width / ratio;
const height = options.height || this.canvas.height / ratio;
const xOffset = options.xOffset || 0;
const yOffset = options.yOffset || 0;
this._reset();
this._reset();
image.onload = (): void => {
this._ctx.drawImage(image, 0, 0, width, height);
if (callback) {
callback();
}
};
image.onerror = (error): void => {
if (callback) {
callback(error);
}
};
image.src = dataUrl;
image.onload = (): void => {
this._ctx.drawImage(image, xOffset, yOffset, width, height);
resolve();
};
image.onerror = (error): void => {
reject(error);
};
image.crossOrigin = 'anonymous';
image.src = dataUrl;
this._isEmpty = false;
this._isEmpty = false;
});
}

@@ -175,5 +180,5 @@

this.canvas.removeEventListener('pointerdown', this._handleMouseDown);
this.canvas.removeEventListener('pointermove', this._handleMouseMove);
document.removeEventListener('pointerup', this._handleMouseUp);
this.canvas.removeEventListener('pointerdown', this._handlePointerStart);
this.canvas.removeEventListener('pointermove', this._handlePointerMove);
document.removeEventListener('pointerup', this._handlePointerEnd);

@@ -193,12 +198,17 @@ this.canvas.removeEventListener('mousedown', this._handleMouseDown);

public fromData(pointGroups: PointGroup[]): void {
this.clear();
public fromData(
pointGroups: PointGroup[],
{ clear = true }: FromDataOptions = {},
): void {
if (clear) {
this.clear();
}
this._fromData(
pointGroups,
({ color, curve }) => this._drawCurve({ color, curve }),
({ color, point }) => this._drawDot({ color, point }),
this._drawCurve.bind(this),
this._drawDot.bind(this),
);
this._data = pointGroups;
this._data = clear ? pointGroups : this._data.concat(pointGroups);
}

@@ -212,4 +222,4 @@

private _handleMouseDown = (event: MouseEvent): void => {
if (event.which === 1) {
this._mouseButtonDown = true;
if (event.buttons === 1) {
this._drawningStroke = true;
this._strokeBegin(event);

@@ -220,3 +230,3 @@ }

private _handleMouseMove = (event: MouseEvent): void => {
if (this._mouseButtonDown) {
if (this._drawningStroke) {
this._strokeMoveUpdate(event);

@@ -227,4 +237,4 @@ }

private _handleMouseUp = (event: MouseEvent): void => {
if (event.which === 1 && this._mouseButtonDown) {
this._mouseButtonDown = false;
if (event.buttons === 1 && this._drawningStroke) {
this._drawningStroke = false;
this._strokeEnd(event);

@@ -262,13 +272,36 @@ }

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);
}
};
private _handlePointerEnd = (event: PointerEvent): void => {
this._drawningStroke = false;
const wasCanvasTouched = event.target === this.canvas;
if (wasCanvasTouched) {
event.preventDefault();
this._strokeEnd(event);
}
};
// Private methods
private _strokeBegin(event: MouseEvent | Touch): void {
const newPointGroup = {
color: this.penColor,
private _strokeBegin(event: SignatureEvent): void {
this.dispatchEvent(new CustomEvent('beginStroke', { detail: event }));
const newPointGroup: PointGroup = {
dotSize: this.dotSize,
minWidth: this.minWidth,
maxWidth: this.maxWidth,
penColor: this.penColor,
points: [],
};
if (typeof this.onBegin === 'function') {
this.onBegin(event);
}
this._data.push(newPointGroup);

@@ -279,3 +312,3 @@ this._reset();

private _strokeUpdate(event: MouseEvent | Touch): void {
private _strokeUpdate(event: SignatureEvent): void {
if (this._data.length === 0) {

@@ -288,6 +321,16 @@ // This can happen if clear() was called while a signature is still in progress,

this.dispatchEvent(
new CustomEvent('beforeUpdateStroke', { detail: event }),
);
const x = event.clientX;
const y = event.clientY;
const pressure =
(event as PointerEvent).pressure !== undefined
? (event as PointerEvent).pressure
: (event as Touch).force !== undefined
? (event as Touch).force
: 0;
const point = this._createPoint(x, y);
const point = this._createPoint(x, y, pressure);
const lastPointGroup = this._data[this._data.length - 1];

@@ -300,3 +343,3 @@ const lastPoints = lastPointGroup.points;

: false;
const color = lastPointGroup.color;
const { penColor, dotSize, minWidth, maxWidth } = lastPointGroup;

@@ -308,5 +351,15 @@ // Skip this point if it's too close to the previous one

if (!lastPoint) {
this._drawDot({ color, point });
this._drawDot(point, {
penColor,
dotSize,
minWidth,
maxWidth,
});
} else if (curve) {
this._drawCurve({ color, curve });
this._drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -318,24 +371,25 @@

y: point.y,
pressure: point.pressure,
});
}
this.dispatchEvent(new CustomEvent('afterUpdateStroke', { detail: event }));
}
private _strokeEnd(event: MouseEvent | Touch): void {
private _strokeEnd(event: SignatureEvent): void {
this._strokeUpdate(event);
if (typeof this.onEnd === 'function') {
this.onEnd(event);
}
this.dispatchEvent(new CustomEvent('endStroke', { detail: event }));
}
private _handlePointerEvents(): void {
this._mouseButtonDown = false;
this._drawningStroke = false;
this.canvas.addEventListener('pointerdown', this._handleMouseDown);
this.canvas.addEventListener('pointermove', this._handleMouseMove);
document.addEventListener('pointerup', this._handleMouseUp);
this.canvas.addEventListener('pointerdown', this._handlePointerStart);
this.canvas.addEventListener('pointermove', this._handlePointerMove);
document.addEventListener('pointerup', this._handlePointerEnd);
}
private _handleMouseEvents(): void {
this._mouseButtonDown = false;
this._drawningStroke = false;

@@ -361,6 +415,11 @@ this.canvas.addEventListener('mousedown', this._handleMouseDown);

private _createPoint(x: number, y: number): Point {
private _createPoint(x: number, y: number, pressure: number): Point {
const rect = this.canvas.getBoundingClientRect();
return new Point(x - rect.left, y - rect.top, new Date().getTime());
return new Point(
x - rect.left,
y - rect.top,
pressure,
new Date().getTime(),
);
}

@@ -427,3 +486,3 @@

private _drawCurve({ color, curve }: { color: string; curve: Bezier }): void {
private _drawCurve(curve: Bezier, options: PointGroupOptions): void {
const ctx = this._ctx;

@@ -433,6 +492,6 @@ const widthDelta = curve.endWidth - curve.startWidth;

// there are gaps between curve segments :/
const drawSteps = Math.floor(curve.length()) * 2;
const drawSteps = Math.ceil(curve.length()) * 2;
ctx.beginPath();
ctx.fillStyle = color;
ctx.fillStyle = options.penColor;

@@ -460,3 +519,3 @@ for (let i = 0; i < drawSteps; i += 1) {

curve.startWidth + ttt * widthDelta,
this.maxWidth,
options.maxWidth,
);

@@ -470,12 +529,8 @@ this._drawCurveSegment(x, y, width);

private _drawDot({
color,
point,
}: {
color: string;
point: BasicPoint;
}): void {
private _drawDot(point: BasicPoint, options: PointGroupOptions): void {
const ctx = this._ctx;
const width =
typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;
options.dotSize > 0
? options.dotSize
: (options.minWidth + options.maxWidth) / 2;

@@ -485,3 +540,3 @@ ctx.beginPath();

ctx.closePath();
ctx.fillStyle = color;
ctx.fillStyle = options.penColor;
ctx.fill();

@@ -496,3 +551,3 @@ }

for (const group of pointGroups) {
const { color, points } = group;
const { penColor, dotSize, minWidth, maxWidth, points } = group;

@@ -502,7 +557,12 @@ if (points.length > 1) {

const basicPoint = points[j];
const point = new Point(basicPoint.x, basicPoint.y, basicPoint.time);
const point = new Point(
basicPoint.x,
basicPoint.y,
basicPoint.pressure,
basicPoint.time,
);
// All points in the group have the same color, so it's enough to set
// penColor just at the beginning.
this.penColor = color;
this.penColor = penColor;

@@ -516,3 +576,8 @@ if (j === 0) {

if (curve) {
drawCurve({ color, curve });
drawCurve(curve, {
penColor,
dotSize,
minWidth,
maxWidth,
});
}

@@ -523,5 +588,7 @@ }

drawDot({
color,
point: points[0],
drawDot(points[0], {
penColor,
dotSize,
minWidth,
maxWidth,
});

@@ -547,3 +614,3 @@ }

({ color, curve }: { color: string; curve: Bezier }) => {
(curve, { penColor }) => {
const path = document.createElement('path');

@@ -570,3 +637,3 @@

path.setAttribute('stroke-width', (curve.endWidth * 2.25).toFixed(3));
path.setAttribute('stroke', color);
path.setAttribute('stroke', penColor);
path.setAttribute('fill', 'none');

@@ -580,10 +647,9 @@ path.setAttribute('stroke-linecap', 'round');

({ color, point }: { color: string; point: BasicPoint }) => {
(point, { penColor, dotSize, minWidth, maxWidth }) => {
const circle = document.createElement('circle');
const dotSize =
typeof this.dotSize === 'function' ? this.dotSize() : this.dotSize;
circle.setAttribute('r', dotSize.toString());
const size = dotSize > 0 ? dotSize : (minWidth + maxWidth) / 2;
circle.setAttribute('r', size.toString());
circle.setAttribute('cx', point.x.toString());
circle.setAttribute('cy', point.y.toString());
circle.setAttribute('fill', color);
circle.setAttribute('fill', penColor);

@@ -599,3 +665,3 @@ svg.appendChild(circle);

' xmlns:xlink="http://www.w3.org/1999/xlink"' +
` viewBox="${minX} ${minY} ${maxX} ${maxY}"` +
` viewBox="${minX} ${minY} ${this.canvas.width} ${this.canvas.height}"` +
` width="${maxX}"` +

@@ -602,0 +668,0 @@ ` height="${maxY}"` +

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc