signature_pad
Advanced tools
Comparing version
/*! | ||
* Signature Pad v4.0.4 | https://github.com/szimek/signature_pad | ||
* Signature Pad v4.0.5 | https://github.com/szimek/signature_pad | ||
* (c) 2022 Szymon Nowak | Released under the MIT license | ||
@@ -4,0 +4,0 @@ */ |
/*! | ||
* Signature Pad v4.0.4 | https://github.com/szimek/signature_pad | ||
* Signature Pad v4.0.5 | https://github.com/szimek/signature_pad | ||
* (c) 2022 Szymon Nowak | Released under the MIT license | ||
*/ | ||
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,c=(i.x+s.x)/2,l=(i.y+s.y)/2,u=Math.sqrt(n*n+o*o),v=Math.sqrt(h*h+r*r),m=v/(u+v),_=c+(a-c)*m,p=l+(d-l)*m,g=i.x-_,w=i.y-p;return{c1:new t(a+g,d+w),c2:new t(c+g,l+w)}}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 class{constructor(){try{this._et=new EventTarget}catch(t){this._et=document}}addEventListener(t,e,i){this._et.addEventListener(t,e,i)}dispatchEvent(t){return this._et.dispatchEvent(t)}removeEventListener(t,e,i){this._et.removeEventListener(t,e,i)}}{constructor(t,e={}){super(),this.canvas=t,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&&(t.preventDefault(),this._drawningStroke=!1,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(),c=e-(d-o);return s=this,n=a,c<=0||c>e?(h&&(clearTimeout(h),h=null),o=d,i=t.apply(s,n),h||(s=null,n=[])):h||(h=window.setTimeout(r,c)),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",this.canvas.style.userSelect="none";const t=/Macintosh/.test(navigator.userAgent)&&"ontouchstart"in document;window.PointerEvent&&!t?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.style.userSelect="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=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:c,minWidth:l,maxWidth:u}=o;if(!r||!r||!a){const t=this._addPoint(n);r?t&&this._drawCurve(t,{penColor:d,dotSize:c,minWidth:l,maxWidth:u}):this._drawDot(n,{penColor:d,dotSize:c,minWidth:l,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,c=d*a;let l=c*t.startPoint.x;l+=3*d*o*t.control1.x,l+=3*a*h*t.control2.x,l+=r*t.endPoint.x;let u=c*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(l,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 c=this._addPoint(d);c&&i(c,{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}; | ||
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,c=(i.x+s.x)/2,l=(i.y+s.y)/2,u=Math.sqrt(n*n+o*o),v=Math.sqrt(h*h+r*r),m=v/(u+v),_=c+(a-c)*m,p=l+(d-l)*m,g=i.x-_,w=i.y-p;return{c1:new t(a+g,d+w),c2:new t(c+g,l+w)}}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 class{constructor(){try{this._et=new EventTarget}catch(t){this._et=document}}addEventListener(t,e,i){this._et.addEventListener(t,e,i)}dispatchEvent(t){return this._et.dispatchEvent(t)}removeEventListener(t,e,i){this._et.removeEventListener(t,e,i)}}{constructor(t,e={}){super(),this.canvas=t,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&&(t.preventDefault(),this._drawningStroke=!1,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(),c=e-(d-o);return s=this,n=a,c<=0||c>e?(h&&(clearTimeout(h),h=null),o=d,i=t.apply(s,n),h||(s=null,n=[])):h||(h=window.setTimeout(r,c)),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){return"image/svg+xml"===t?this._toSVG():this.canvas.toDataURL(t,e)}on(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",this.canvas.style.userSelect="none";const t=/Macintosh/.test(navigator.userAgent)&&"ontouchstart"in document;window.PointerEvent&&!t?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.style.userSelect="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=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:c,minWidth:l,maxWidth:u}=o;if(!r||!r||!a){const t=this._addPoint(n);r?t&&this._drawCurve(t,{penColor:d,dotSize:c,minWidth:l,maxWidth:u}):this._drawDot(n,{penColor:d,dotSize:c,minWidth:l,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,c=d*a;let l=c*t.startPoint.x;l+=3*d*o*t.control1.x,l+=3*a*h*t.control2.x,l+=r*t.endPoint.x;let u=c*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(l,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 c=this._addPoint(d);c&&i(c,{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 v4.0.4 | https://github.com/szimek/signature_pad | ||
* Signature Pad v4.0.5 | https://github.com/szimek/signature_pad | ||
* (c) 2022 Szymon Nowak | Released under the MIT license | ||
@@ -4,0 +4,0 @@ */ |
/*! | ||
* Signature Pad v4.0.4 | https://github.com/szimek/signature_pad | ||
* Signature Pad v4.0.5 | https://github.com/szimek/signature_pad | ||
* (c) 2022 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";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,c=(i.x+n.x)/2,l=(i.y+n.y)/2,u=Math.sqrt(s*s+o*o),v=Math.sqrt(h*h+r*r),m=v/(u+v),_=c+(a-c)*m,p=l+(d-l)*m,g=i.x-_,w=i.y-p;return{c1:new t(a+g,d+w),c2:new t(c+g,l+w)}}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 class{constructor(){try{this._et=new EventTarget}catch(t){this._et=document}}addEventListener(t,e,i){this._et.addEventListener(t,e,i)}dispatchEvent(t){return this._et.dispatchEvent(t)}removeEventListener(t,e,i){this._et.removeEventListener(t,e,i)}}{constructor(t,e={}){super(),this.canvas=t,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&&(t.preventDefault(),this._drawningStroke=!1,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(),c=e-(d-o);return n=this,s=a,c<=0||c>e?(h&&(clearTimeout(h),h=null),o=d,i=t.apply(n,s),h||(n=null,s=[])):h||(h=window.setTimeout(r,c)),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",this.canvas.style.userSelect="none";const t=/Macintosh/.test(navigator.userAgent)&&"ontouchstart"in document;window.PointerEvent&&!t?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.style.userSelect="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=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:c,minWidth:l,maxWidth:u}=o;if(!r||!r||!a){const t=this._addPoint(s);r?t&&this._drawCurve(t,{penColor:d,dotSize:c,minWidth:l,maxWidth:u}):this._drawDot(s,{penColor:d,dotSize:c,minWidth:l,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,c=d*a;let l=c*t.startPoint.x;l+=3*d*o*t.control1.x,l+=3*a*h*t.control2.x,l+=r*t.endPoint.x;let u=c*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(l,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 c=this._addPoint(d);c&&i(c,{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})); | ||
!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,c=(i.x+n.x)/2,l=(i.y+n.y)/2,u=Math.sqrt(s*s+o*o),v=Math.sqrt(h*h+r*r),m=v/(u+v),_=c+(a-c)*m,p=l+(d-l)*m,g=i.x-_,x=i.y-p;return{c1:new t(a+g,d+x),c2:new t(c+g,l+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 class{constructor(){try{this._et=new EventTarget}catch(t){this._et=document}}addEventListener(t,e,i){this._et.addEventListener(t,e,i)}dispatchEvent(t){return this._et.dispatchEvent(t)}removeEventListener(t,e,i){this._et.removeEventListener(t,e,i)}}{constructor(t,e={}){super(),this.canvas=t,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&&(t.preventDefault(),this._drawningStroke=!1,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(),c=e-(d-o);return n=this,s=a,c<=0||c>e?(h&&(clearTimeout(h),h=null),o=d,i=t.apply(n,s),h||(n=null,s=[])):h||(h=window.setTimeout(r,c)),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){return"image/svg+xml"===t?this._toSVG():this.canvas.toDataURL(t,e)}on(){this.canvas.style.touchAction="none",this.canvas.style.msTouchAction="none",this.canvas.style.userSelect="none";const t=/Macintosh/.test(navigator.userAgent)&&"ontouchstart"in document;window.PointerEvent&&!t?this._handlePointerEvents():(this._handleMouseEvents(),"ontouchstart"in window&&this._handleTouchEvents())}off(){this.canvas.style.touchAction="auto",this.canvas.style.msTouchAction="auto",this.canvas.style.userSelect="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=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:c,minWidth:l,maxWidth:u}=o;if(!r||!r||!a){const t=this._addPoint(s);r?t&&this._drawCurve(t,{penColor:d,dotSize:c,minWidth:l,maxWidth:u}):this._drawDot(s,{penColor:d,dotSize:c,minWidth:l,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,c=d*a;let l=c*t.startPoint.x;l+=3*d*o*t.control1.x,l+=3*a*h*t.control2.x,l+=r*t.endPoint.x;let u=c*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(l,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 c=this._addPoint(d);c&&i(c,{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 |
@@ -1,10 +0,10 @@ | ||
var wrapper = document.getElementById("signature-pad"); | ||
var clearButton = wrapper.querySelector("[data-action=clear]"); | ||
var changeColorButton = wrapper.querySelector("[data-action=change-color]"); | ||
var undoButton = wrapper.querySelector("[data-action=undo]"); | ||
var savePNGButton = wrapper.querySelector("[data-action=save-png]"); | ||
var saveJPGButton = wrapper.querySelector("[data-action=save-jpg]"); | ||
var saveSVGButton = wrapper.querySelector("[data-action=save-svg]"); | ||
var canvas = wrapper.querySelector("canvas"); | ||
var signaturePad = new SignaturePad(canvas, { | ||
const wrapper = document.getElementById("signature-pad"); | ||
const clearButton = wrapper.querySelector("[data-action=clear]"); | ||
const changeColorButton = wrapper.querySelector("[data-action=change-color]"); | ||
const undoButton = wrapper.querySelector("[data-action=undo]"); | ||
const savePNGButton = wrapper.querySelector("[data-action=save-png]"); | ||
const saveJPGButton = wrapper.querySelector("[data-action=save-jpg]"); | ||
const saveSVGButton = wrapper.querySelector("[data-action=save-svg]"); | ||
const canvas = wrapper.querySelector("canvas"); | ||
const signaturePad = new SignaturePad(canvas, { | ||
// It's Necessary to use an opaque color when saving image as JPEG; | ||
@@ -22,3 +22,3 @@ // this option can be omitted if only saving as PNG or SVG | ||
// and only part of the canvas is cleared then. | ||
var ratio = Math.max(window.devicePixelRatio || 1, 1); | ||
const ratio = Math.max(window.devicePixelRatio || 1, 1); | ||
@@ -44,18 +44,14 @@ // This part causes the canvas to be cleared | ||
function download(dataURL, filename) { | ||
if (navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1) { | ||
window.open(dataURL); | ||
} else { | ||
var blob = dataURLToBlob(dataURL); | ||
var url = window.URL.createObjectURL(blob); | ||
const blob = dataURLToBlob(dataURL); | ||
const url = window.URL.createObjectURL(blob); | ||
var a = document.createElement("a"); | ||
a.style = "display: none"; | ||
a.href = url; | ||
a.download = filename; | ||
const a = document.createElement("a"); | ||
a.style = "display: none"; | ||
a.href = url; | ||
a.download = filename; | ||
document.body.appendChild(a); | ||
a.click(); | ||
document.body.appendChild(a); | ||
a.click(); | ||
window.URL.revokeObjectURL(url); | ||
} | ||
window.URL.revokeObjectURL(url); | ||
} | ||
@@ -67,9 +63,9 @@ | ||
// Code taken from https://github.com/ebidel/filer.js | ||
var parts = dataURL.split(';base64,'); | ||
var contentType = parts[0].split(":")[1]; | ||
var raw = window.atob(parts[1]); | ||
var rawLength = raw.length; | ||
var uInt8Array = new Uint8Array(rawLength); | ||
const parts = dataURL.split(';base64,'); | ||
const contentType = parts[0].split(":")[1]; | ||
const raw = window.atob(parts[1]); | ||
const rawLength = raw.length; | ||
const uInt8Array = new Uint8Array(rawLength); | ||
for (var i = 0; i < rawLength; ++i) { | ||
for (let i = 0; i < rawLength; ++i) { | ||
uInt8Array[i] = raw.charCodeAt(i); | ||
@@ -81,8 +77,8 @@ } | ||
clearButton.addEventListener("click", function (event) { | ||
clearButton.addEventListener("click", () => { | ||
signaturePad.clear(); | ||
}); | ||
undoButton.addEventListener("click", function (event) { | ||
var data = signaturePad.toData(); | ||
undoButton.addEventListener("click", () => { | ||
const data = signaturePad.toData(); | ||
@@ -95,7 +91,7 @@ if (data) { | ||
changeColorButton.addEventListener("click", function (event) { | ||
var r = Math.round(Math.random() * 255); | ||
var g = Math.round(Math.random() * 255); | ||
var b = Math.round(Math.random() * 255); | ||
var color = "rgb(" + r + "," + g + "," + b +")"; | ||
changeColorButton.addEventListener("click", () => { | ||
const r = Math.round(Math.random() * 255); | ||
const g = Math.round(Math.random() * 255); | ||
const b = Math.round(Math.random() * 255); | ||
const color = "rgb(" + r + "," + g + "," + b +")"; | ||
@@ -105,7 +101,7 @@ signaturePad.penColor = color; | ||
savePNGButton.addEventListener("click", function (event) { | ||
savePNGButton.addEventListener("click", () => { | ||
if (signaturePad.isEmpty()) { | ||
alert("Please provide a signature first."); | ||
} else { | ||
var dataURL = signaturePad.toDataURL(); | ||
const dataURL = signaturePad.toDataURL(); | ||
download(dataURL, "signature.png"); | ||
@@ -115,7 +111,7 @@ } | ||
saveJPGButton.addEventListener("click", function (event) { | ||
saveJPGButton.addEventListener("click", () => { | ||
if (signaturePad.isEmpty()) { | ||
alert("Please provide a signature first."); | ||
} else { | ||
var dataURL = signaturePad.toDataURL("image/jpeg"); | ||
const dataURL = signaturePad.toDataURL("image/jpeg"); | ||
download(dataURL, "signature.jpg"); | ||
@@ -125,9 +121,9 @@ } | ||
saveSVGButton.addEventListener("click", function (event) { | ||
saveSVGButton.addEventListener("click", () => { | ||
if (signaturePad.isEmpty()) { | ||
alert("Please provide a signature first."); | ||
} else { | ||
var dataURL = signaturePad.toDataURL('image/svg+xml'); | ||
const dataURL = signaturePad.toDataURL('image/svg+xml'); | ||
download(dataURL, "signature.svg"); | ||
} | ||
}); |
/*! | ||
* Signature Pad v4.0.4 | https://github.com/szimek/signature_pad | ||
* Signature Pad v4.0.5 | https://github.com/szimek/signature_pad | ||
* (c) 2022 Szymon Nowak | Released under the MIT license | ||
@@ -4,0 +4,0 @@ */ |
{ | ||
"name": "signature_pad", | ||
"description": "Library for drawing smooth signatures.", | ||
"version": "4.0.4", | ||
"version": "4.0.5", | ||
"homepage": "https://github.com/szimek/signature_pad", | ||
@@ -39,30 +39,31 @@ "author": { | ||
"devDependencies": { | ||
"@rollup/plugin-typescript": "^8.3.0", | ||
"@rollup/plugin-typescript": "^8.3.2", | ||
"@semantic-release/changelog": "^6.0.1", | ||
"@semantic-release/commit-analyzer": "^9.0.2", | ||
"@semantic-release/git": "^10.0.1", | ||
"@semantic-release/github": "^8.0.2", | ||
"@semantic-release/npm": "^8.0.3", | ||
"@semantic-release/github": "^8.0.4", | ||
"@semantic-release/npm": "^9.0.1", | ||
"@semantic-release/release-notes-generator": "^10.0.3", | ||
"@types/jest": "^27.4.0", | ||
"@types/node": "^17.0.8", | ||
"@typescript-eslint/eslint-plugin": "^5.9.0", | ||
"@typescript-eslint/parser": "^5.9.0", | ||
"canvas": "^2.8.0", | ||
"@types/jest": "^28.1.1", | ||
"@types/node": "^17.0.39", | ||
"@typescript-eslint/eslint-plugin": "^5.27.0", | ||
"@typescript-eslint/parser": "^5.27.0", | ||
"cp-cli": "^2.0.0", | ||
"del": "^6.0.0", | ||
"del": "^6.1.1", | ||
"del-cli": "^4.0.1", | ||
"eslint": "^8.6.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"husky": "^7.0.4", | ||
"jest": "^27.4.7", | ||
"lint-staged": "^12.1.7", | ||
"prettier": "^2.5.1", | ||
"rollup": "^2.63.0", | ||
"eslint": "^8.17.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"husky": "^8.0.1", | ||
"jest": "^28.1.0", | ||
"jest-canvas-mock": "^2.4.0", | ||
"jest-environment-jsdom": "^28.1.0", | ||
"lint-staged": "^13.0.0", | ||
"prettier": "^2.6.2", | ||
"rollup": "^2.75.5", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"semantic-release": "^18.0.1", | ||
"semantic-release": "^19.0.2", | ||
"serve": "^13.0.2", | ||
"ts-jest": "^27.1.2", | ||
"tslib": "^2.3.1", | ||
"typescript": "^4.5.4" | ||
"ts-jest": "^28.0.4", | ||
"tslib": "^2.4.0", | ||
"typescript": "^4.7.3" | ||
}, | ||
@@ -79,3 +80,4 @@ "lint-staged": { | ||
"testEnvironmentOptions": { | ||
"resources": "usable" | ||
"resources": "usable", | ||
"url": "http://localhost:3000/" | ||
}, | ||
@@ -85,6 +87,8 @@ "testMatch": [ | ||
], | ||
"testURL": "http://localhost:3000/", | ||
"transform": { | ||
"^.+\\.tsx?$": "ts-jest" | ||
} | ||
}, | ||
"setupFiles": [ | ||
"jest-canvas-mock" | ||
] | ||
}, | ||
@@ -100,3 +104,4 @@ "release": { | ||
] | ||
} | ||
}, | ||
"packageManager": "yarn@3.2.1" | ||
} |
@@ -13,2 +13,3 @@ # Signature Pad [](https://www.npmjs.com/package/signature_pad) [](https://github.com/szimek/signature_pad/actions/workflows/test.yml) [](https://codeclimate.com/github/szimek/signature_pad) [](https://www.jsdelivr.com/package/npm/signature_pad) | ||
### Other demos | ||
- Erase feature: <https://jsfiddle.net/szimek/jq9cyzuc/> | ||
@@ -18,7 +19,11 @@ - Undo feature: <https://jsfiddle.net/szimek/osenxvjc/> | ||
## Installation | ||
You can install the latest release using npm: | ||
```bash | ||
npm install --save signature_pad | ||
``` | ||
or Yarn: | ||
```bash | ||
@@ -29,5 +34,7 @@ yarn add signature_pad | ||
You can also add it directly to your page using `<script>` tag: | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.0.0/dist/signature_pad.umd.min.js"></script> | ||
``` | ||
You can select a different version at [https://www.jsdelivr.com/package/npm/signature_pad](https://www.jsdelivr.com/package/npm/signature_pad). | ||
@@ -38,4 +45,6 @@ | ||
## Usage | ||
### API | ||
``` javascript | ||
```javascript | ||
const canvas = document.querySelector("canvas"); | ||
@@ -48,8 +57,12 @@ | ||
signaturePad.toDataURL("image/jpeg"); // save image as JPEG | ||
signaturePad.toDataURL("image/jpeg", 0.5); // save image as JPEG with 0.5 image quality | ||
signaturePad.toDataURL("image/svg+xml"); // save image as SVG | ||
// Draws signature image from data URL. | ||
// Draws signature image from data URL (mostly uses https://mdn.io/drawImage under-the-hood) | ||
// NOTE: This method does not populate internal data structure that represents drawn signature. Thus, after using #fromDataURL, #toData won't work properly. | ||
signaturePad.fromDataURL("data:image/png;base64,iVBORw0K..."); | ||
// Draws signature image from data URL and alters it with the given options | ||
signaturePad.fromDataURL("data:image/png;base64,iVBORw0K...", { ratio: 1, width: 400, height: 200, xOffset: 100, yOffset: 50 }); | ||
// Returns signature image as an array of point groups | ||
@@ -78,2 +91,3 @@ const data = signaturePad.toData(); | ||
### Options | ||
<dl> | ||
@@ -99,2 +113,3 @@ <dt>dotSize</dt> | ||
You can set options during initialization: | ||
```javascript | ||
@@ -107,3 +122,5 @@ const signaturePad = new SignaturePad(canvas, { | ||
``` | ||
or during runtime: | ||
```javascript | ||
@@ -117,2 +134,3 @@ const signaturePad = new SignaturePad(canvas); | ||
### Events | ||
<dl> | ||
@@ -130,2 +148,3 @@ <dt>beginStroke</dt> | ||
You can add listeners to events with [`.addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener): | ||
```javascript | ||
@@ -139,4 +158,7 @@ const signaturePad = new SignaturePad(canvas); | ||
### Tips and tricks | ||
#### Handling high DPI screens | ||
To correctly handle canvas on low and high DPI screens one has to take `devicePixelRatio` into account and scale the canvas accordingly. This scaling is also necessary to properly display signatures loaded via `SignaturePad#fromDataURL`. Here's an example how it can be done: | ||
```javascript | ||
@@ -154,2 +176,3 @@ function resizeCanvas() { | ||
``` | ||
Instead of `resize` event you can listen to screen orientation change, if you're using this library only on mobile devices. You can also throttle the `resize` event - you can find some examples on [this MDN page](https://developer.mozilla.org/en-US/docs/Web/Events/resize). | ||
@@ -162,2 +185,3 @@ | ||
#### Handling data URI encoded images on the server side | ||
If you are not familiar with data URI scheme, you can read more about it on [Wikipedia](http://en.wikipedia.org/wiki/Data_URI_scheme). | ||
@@ -169,3 +193,3 @@ | ||
``` html | ||
```html | ||
<img src="data:image/png;base64,iVBORw0K..." /> | ||
@@ -178,3 +202,3 @@ ``` | ||
``` ruby | ||
```ruby | ||
require "base64" | ||
@@ -190,3 +214,3 @@ | ||
``` php | ||
```php | ||
$data_uri = "data:image/png;base64,iVBORw0K..."; | ||
@@ -200,3 +224,3 @@ $encoded_image = explode(",", $data_uri)[1]; | ||
``` csharp | ||
```csharp | ||
var dataUri = "data:image/png;base64,iVBORw0K..."; | ||
@@ -209,8 +233,11 @@ var encodedImage = dataUri.Split(',')[1]; | ||
#### Removing empty space around a signature | ||
If you'd like to remove (trim) empty space around a signature, you can do it on the server side or the client side. On the server side you can use e.g. ImageMagic and its `trim` option: `convert -trim input.jpg output.jpg`. If you don't have access to the server, or just want to trim the image before submitting it to the server, you can do it on the client side as well. There are a few examples how to do it, e.g. [here](https://github.com/szimek/signature_pad/issues/49#issue-29108215) or [here](https://github.com/szimek/signature_pad/issues/49#issuecomment-260976909) and there's also a tiny library [trim-canvas](https://github.com/agilgur5/trim-canvas) that provides this functionality. | ||
#### Drawing over an image | ||
Demo: <https://jsfiddle.net/szimek/d6a78gwq/> | ||
## License | ||
Released under the [MIT License](http://www.opensource.org/licenses/MIT). |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable @typescript-eslint/no-explicit-any */ | ||
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-this-alias */ | ||
// Slightly simplified version of http://stackoverflow.com/a/27078401/815507 | ||
@@ -3,0 +3,0 @@ |
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
Sorry, the diff of this file is not supported yet
230131
1.96%27
3.85%2942
0.03%226
13.57%29
3.57%