signature_pad
Advanced tools
Comparing version 4.0.4 to 4.0.5
/*! | ||
* 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 [![npm](https://badge.fury.io/js/signature_pad.svg)](https://www.npmjs.com/package/signature_pad) [![tests](https://github.com/szimek/signature_pad/actions/workflows/test.yml/badge.svg)](https://github.com/szimek/signature_pad/actions/workflows/test.yml) [![Code Climate](https://codeclimate.com/github/szimek/signature_pad.png)](https://codeclimate.com/github/szimek/signature_pad) [![](https://data.jsdelivr.com/v1/package/npm/signature_pad/badge?style=rounded)](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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
230131
27
2942
226
29