1const Default = { 2 "lineWidth": 1, 3 "strokeStyle": "#222222", 4 "lineCap": "butt", 5 "lineJoin": "mitter", 6 "backgroundColor": null 7}; 8 9const sigpadMap = new Map(); 10 11export default class Sigpad { 12 13 14 static getOrCreateInstance(element, config) { 15 return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null) 16 } 17 18 static getInstance(element) { 19 if (sigpadMap.has(element)) { 20 return sigpadMap.get(element); 21 } 22 return null; 23 } 24 25 static getAllInstances() { 26 var instances = []; 27 sigpadMap.forEach((value, key, map) => { 28 instances.push(value); 29 }); 30 return instances; 31 } 32 33 constructor(element, options) { 34 35 if (!sigpadMap.has(element)) { 36 sigpadMap.set(element, this); 37 } 38 39 this._config = this._getConfig(options); 40 this._element = element; 41 this._mousePos = null; 42 this._lastPos = null; 43 this._drawing = false; 44 45 this._setListeners(); 46 this._applyOptions(); 47 48 this._element.width = this._element.clientWidth; 49 this._element.height = this._element.clientHeight; 50 } 51 52 destroy() { 53 if (!sigpadMap.has(this._element)) { 54 return 55 } 56 57 sigpadMap.delete(this._element); 58 59 this._element.removeEventListener("mousedown", this._onStart); 60 this._element.removeEventListener("mouseup", this._onEnd); 61 this._element.removeEventListener("mousemove", this._onMove); 62 63 this._element.removeEventListener("touchstart", this._onStart); 64 this._element.removeEventListener("touchend", this._onEnd); 65 this._element.removeEventListener("touchmove", this._onMove); 66 } 67 68 _applyOptions(ctx = null) { 69 if (ctx == null) { 70 ctx = this._element.getContext("2d"); 71 } 72 ctx.strokeStyle = this._config.strokeStyle; 73 ctx.lineWidth = this._config.lineWidth; 74 ctx.lineCap = this._config.lineCap; 75 ctx.lineJoin = this._config.lineJoin; 76 } 77 78 _getRelativeMousePos(e) { 79 var r = this._element.getBoundingClientRect(); 80 81 var x = e.clientX; 82 var y = e.clientY; 83 84 var startX = r.left; 85 var startY = r.top; 86 var w = r.right - r.left; 87 var h = r.bottom - r.top; 88 89 var endX = startX + w; 90 var endY = startY + h; 91 92 if (x < startX || y < startY || x > endX || y > endY) { 93 return null; 94 } else { 95 return { 96 x: x - startX, 97 y: y - startY 98 }; 99 } 100 } 101 102 clear() { 103 var ctx = this._element.getContext("2d"); 104 ctx.clearRect(0, 0, this._element.width, this._element.height); 105 ctx.save(); 106 107 this._mousePos = null; 108 this._lastPos = null; 109 this._drawing = false; 110 111 } 112 113 getImage() { 114 return this._element.toDataURL(); 115 } 116 117 setImage(image) { 118 var ctx = this._element.getContext("2d"); 119 120 if (this._config.backgroundColor != null && this._config.backgroundColor != "") { 121 ctx.fillStyle = this._config.backgroundColor; 122 ctx.fillRect(0, 0, this._element.width, this._element.height); 123 } 124 125 if (this._config.backgroundImage != null && this._config.backgroundImage != "") { 126 this.setBackgroundImage(this._config.backgroundImage); 127 } 128 129 ctx.clearRect(0, 0, this._element.width, this._element.height); 130 131 var img = new Image(); 132 133 img.onload = function () { 134 ctx.drawImage(img, 0, 0); 135 } 136 img.src = image; 137 138 } 139 140 setBackgroundImage(image) { 141 var ctx = this._element.getContext("2d"); 142 143 if (this._config.backgroundImage != null && this._config.backgroundImage != "") { 144 image = this._config.backgroundImage; 145 } 146 147 var img = new Image(); 148 img.onload = function () { 149 ctx.drawImage(img, 0, 0, 150 img.width * window.devicePixelRatio, 151 img.height * window.devicePixelRatio, 152 0, 0, 153 img.width * window.devicePixelRatio, 154 img.height * window.devicePixelRatio 155 ); 156 } 157 158 img.src = image; 159 } 160 161 _getConfig(config) { 162 return { 163 ...Default, 164 ...config, 165 ...(typeof config === 'object' && config ? config : {}) 166 } 167 } 168 169 170 _setListeners() { 171 this._element.addEventListener("mousedown", this._onStart); 172 this._element.addEventListener("mouseup", this._onEnd); 173 this._element.addEventListener("mousemove", this._onMove); 174 175 this._element.addEventListener("touchstart", this._onStart); 176 this._element.addEventListener("touchend", this._onEnd); 177 this._element.addEventListener("touchmove", this._onMove); 178 } 179 180 _onStart(mouseEvent) { 181 182 183 184 if ("touches" in mouseEvent) { 185 mouseEvent.preventDefault(); 186 mouseEvent = mouseEvent.touches[0]; 187 } 188 189 var data = Sigpad.getInstance(this); 190 191 if (data._element.classList.contains('disabled')) { 192 return; 193 } 194 195 var mousePos = data._getRelativeMousePos(mouseEvent); 196 if (mousePos != null) { 197 data._mousePos = null;
198 data._lastPos = null; 199 data._lastPos = mousePos; 200 data._drawing = true; 201 202 const event = new CustomEvent('sigpad.start', { detail: data.getImage() }); 203 data._element.dispatchEvent(event); 204 } 205 } 206 207 _onEnd(mouseEvent) { 208 209 210 if ("touches" in mouseEvent) { 211 mouseEvent.preventDefault(); 212 mouseEvent = mouseEvent.touches[0]; 213 } 214 215 var data = Sigpad.getInstance(this); 216 217 if (data._element.classList.contains('disabled')) { 218 return; 219 } 220 221 data._drawing = false; 222 223 const event = new CustomEvent('sigpad.finish', { detail: data.getImage() }); 224 data._element.dispatchEvent(event); 225 } 226 227 _onMove(mouseEvent) { 228 229 if ("touches" in mouseEvent) { 230 mouseEvent.preventDefault(); 231 mouseEvent = mouseEvent.touches[0]; 232 } 233 234 var data = Sigpad.getInstance(this); 235 236 if (data._element.classList.contains('disabled')) { 237 return; 238 } 239 240 if (data._drawing) { 241 242 var pos = data._getRelativeMousePos(mouseEvent); 243 if (pos != null) { 244 data._mousePos = pos; 245 const event = new CustomEvent('sigpad.move', { detail: data.getImage() }); 246 data._element.dispatchEvent(event); 247 } else { 248 data._onEnd(); 249 } 250 } 251 } 252 253 render() { 254 if (this._element.width != this._element.clientWidth) { 255 this._element.width = this._element.clientWidth; 256 } 257 if (this._drawing && (this._lastPos != null && typeof this._lastPos != "undefined") && (this._mousePos != null && typeof this._mousePos != "undefined")) { 258 259 var ctx = this._element.getContext("2d"); 260 ctx.beginPath(); 261 this._applyOptions(ctx); 262 ctx.moveTo(this._lastPos.x, this._lastPos.y); 263 ctx.lineTo(this._mousePos.x, this._mousePos.y); 264 ctx.closePath(); 265 ctx.stroke(); 266 this._lastPos = this._mousePos; 267 } 268 } 269} 270 271 272 273const requestAnimFrame = (function (callback) { 274 return window.requestAnimationFrame || 275 window.webkitRequestAnimationFrame || 276 window.mozRequestAnimationFrame || 277 window.oRequestAnimationFrame || 278 window.msRequestAnimaitonFrame || 279 function (callback) { 280 window.setTimeout(callback, 1000 / 144); 281 }; 282})(); 283
284(function renderSignatures() { 285 requestAnimFrame(renderSignatures); 286 Sigpad.getAllInstances().forEach((sigpad, index) => { 287 sigpad.render(); 288 }); 289 290})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.