vendor: 5,888 bytes, lines 1-163
1/*! 2 * Signature Pad v5.0.4 | https://github.com/szimek/signature_pad 3 * (c) 2024 Szymon Nowak | Released under the MIT license 4 */ 5 6(function (global, factory) { 7 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 8 typeof define === 'function' && define.amd ? define(factory) : 9 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SignaturePad = factory()); 10})(this, (function () { 'use strict'; 11 12 class Point { 13 constructor(x, y, pressure, time) { 14 if (isNaN(x) || isNaN(y)) { 15 throw new Error(`Point is invalid: (${x}, ${y})`); 16 } 17 this.x = +x; 18 this.y = +y; 19 this.pressure = pressure || 0; 20 this.time = time || Date.now(); 21 } 22 distanceTo(start) { 23 return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2)); 24 } 25 equals(other) { 26 return (this.x === other.x && 27 this.y === other.y && 28 this.pressure === other.pressure && 29 this.time === other.time); 30 } 31 velocityFrom(start) { 32 return this.time !== start.time 33 ? this.distanceTo(start) / (this.time - start.time) 34 : 0; 35 } 36 } 37 38 class Bezier { 39 static fromPoints(points, widths) { 40 const c2 = this.calculateControlPoints(points[0], points[1], points[2]).c2; 41 const c3 = this.calculateControlPoints(points[1], points[2], points[3]).c1; 42 return new Bezier(points[1], c2, c3, points[2], widths.start, widths.end); 43 } 44 static calculateControlPoints(s1, s2, s3) { 45 const dx1 = s1.x - s2.x; 46 const dy1 = s1.y - s2.y; 47 const dx2 = s2.x - s3.x; 48 const dy2 = s2.y - s3.y; 49 const m1 = { x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0 }; 50 const m2 = { x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0 }; 51 const l1 = Math.sqrt(dx1 * dx1 + dy1 * dy1); 52 const l2 = Math.sqrt(dx2 * dx2 + dy2 * dy2); 53 const dxm = m1.x - m2.x; 54 const dym = m1.y - m2.y; 55 const k = l1 + l2 == 0 ? 0 : l2 / (l1 + l2); 56 const cm = { x: m2.x + dxm * k, y: m2.y + dym * k }; 57 const tx = s2.x - cm.x; 58 const ty = s2.y - cm.y; 59 return { 60 c1: new Point(m1.x + tx, m1.y + ty), 61 c2: new Point(m2.x + tx, m2.y + ty), 62 }; 63 } 64 constructor(startPoint, control2, control1, endPoint, startWidth, endWidth) { 65 this.startPoint = startPoint; 66 this.control2 = control2; 67 this.control1 = control1; 68 this.endPoint = endPoint; 69 this.startWidth = startWidth; 70 this.endWidth = endWidth; 71 } 72 length() { 73 const steps = 10; 74 let length = 0; 75 let px; 76 let py; 77 for (let i = 0; i <= steps; i += 1) { 78 const t = i / steps; 79 const cx = this.point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x); 80 const cy = this.point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y); 81 if (i > 0) { 82 const xdiff = cx - px; 83 const ydiff = cy - py; 84 length += Math.sqrt(xdiff * xdiff + ydiff * ydiff); 85 } 86 px = cx; 87 py = cy; 88 } 89 return length; 90 } 91 point(t, start, c1, c2, end) { 92 return (start * (1.0 - t) * (1.0 - t) * (1.0 - t)) 93 + (3.0 * c1 * (1.0 - t) * (1.0 - t) * t) 94 + (3.0 * c2 * (1.0 - t) * t * t) 95 + (end * t * t * t); 96 } 97 } 98 99 class SignatureEventTarget { 100 constructor() { 101 try { 102 this._et = new EventTarget(); 103 } 104 catch (_a) { 105 this._et = document; 106 } 107 } 108 addEventListener(type, listener, options) { 109 this._et.addEventListener(type, listener, options); 110 } 111 dispatchEvent(event) { 112 return this._et.dispatchEvent(event); 113 } 114 removeEventListener(type, callback, options) { 115 this._et.removeEventListener(type, callback, options); 116 } 117 } 118 119 function throttle(fn, wait = 250) { 120 let previous = 0; 121 let timeout = null; 122 let result; 123 let storedContext; 124 let storedArgs; 125 const later = () => { 126 previous = Date.now(); 127 timeout = null; 128 result = fn.apply(storedContext, storedArgs); 129 if (!timeout) { 130 storedContext = null; 131 storedArgs = []; 132 } 133 }; 134 return function wrapper(...args) { 135 const now = Date.now(); 136 const remaining = wait - (now - previous); 137 storedContext = this; 138 storedArgs = args; 139 if (remaining <= 0 || remaining > wait) { 140 if (timeout) { 141 clearTimeout(timeout); 142 timeout = null; 143 } 144 previous = now; 145 result = fn.apply(storedContext, storedArgs); 146 if (!timeout) { 147 storedContext = null; 148 storedArgs = []; 149 } 150 } 151 else if (!timeout) { 152 timeout = window.setTimeout(later, remaining); 153 } 154 return result; 155 }; 156 } 157 158 class SignaturePad extends SignatureEventTarget { 159 constructor(canvas, options = {}) { 160 var _a, _b, _c; 161 super(); 162 this.canvas = canvas; 163 this._drawingStroke = false;
164 this._isEmpty = true; 165 this._lastPoints = []; 166 this._data = []; 167 this._lastVelocity = 0; 168 this._lastWidth = 0; 169 this._handleMouseDown = (event) => { 170 if (!this._isLeftButtonPressed(event, true) || this._drawingStroke) { 171 return; 172 } 173 this._strokeBegin(this._pointerEventToSignatureEvent(event)); 174 }; 175 this._handleMouseMove = (event) => { 176 if (!this._isLeftButtonPressed(event, true) || !this._drawingStroke) { 177 this._strokeEnd(this._pointerEventToSignatureEvent(event), false); 178 return; 179 } 180 this._strokeMoveUpdate(this._pointerEventToSignatureEvent(event)); 181 }; 182 this._handleMouseUp = (event) => { 183 if (this._isLeftButtonPressed(event)) { 184 return; 185 } 186 this._strokeEnd(this._pointerEventToSignatureEvent(event)); 187 }; 188 this._handleTouchStart = (event) => { 189 if (event.targetTouches.length !== 1 || this._drawingStroke) { 190 return; 191 } 192 if (event.cancelable) { 193 event.preventDefault(); 194 } 195 this._strokeBegin(this._touchEventToSignatureEvent(event)); 196 }; 197 this._handleTouchMove = (event) => { 198 if (event.targetTouches.length !== 1) { 199 return; 200 } 201 if (event.cancelable) { 202 event.preventDefault(); 203 } 204 if (!this._drawingStroke) { 205 this._strokeEnd(this._touchEventToSignatureEvent(event), false); 206 return; 207 } 208 this._strokeMoveUpdate(this._touchEventToSignatureEvent(event)); 209 }; 210 this._handleTouchEnd = (event) => { 211 if (event.targetTouches.length !== 0) { 212 return; 213 } 214 if (event.cancelable) { 215 event.preventDefault(); 216 } 217 this.canvas.removeEventListener('touchmove', this._handleTouchMove); 218 this._strokeEnd(this._touchEventToSignatureEvent(event)); 219 }; 220 this._handlePointerDown = (event) => { 221 if (!event.isPrimary || !this._isLeftButtonPressed(event) || this._drawingStroke) { 222 return; 223 } 224 event.preventDefault(); 225 this._strokeBegin(this._pointerEventToSignatureEvent(event)); 226 }; 227 this._handlePointerMove = (event) => { 228 if (!event.isPrimary) { 229 return; 230 } 231 if (!this._isLeftButtonPressed(event, true) || !this._drawingStroke) { 232 this._strokeEnd(this._pointerEventToSignatureEvent(event), false); 233 return; 234 } 235 event.preventDefault(); 236 this._strokeMoveUpdate(this._pointerEventToSignatureEvent(event)); 237 }; 238 this._handlePointerUp = (event) => { 239 if (!event.isPrimary || this._isLeftButtonPressed(event)) { 240 return; 241 } 242 event.preventDefault(); 243 this._strokeEnd(this._pointerEventToSignatureEvent(event)); 244 }; 245 this.velocityFilterWeight = options.velocityFilterWeight || 0.7; 246 this.minWidth = options.minWidth || 0.5; 247 this.maxWidth = options.maxWidth || 2.5; 248 this.throttle = (_a = options.throttle) !== null && _a !== void 0 ? _a : 16; 249 this.minDistance = (_b = options.minDistance) !== null && _b !== void 0 ? _b : 5; 250 this.dotSize = options.dotSize || 0; 251 this.penColor = options.penColor || 'black'; 252 this.backgroundColor = options.backgroundColor || 'rgba(0,0,0,0)'; 253 this.compositeOperation = options.compositeOperation || 'source-over'; 254 this.canvasContextOptions = (_c = options.canvasContextOptions) !== null && _c !== void 0 ? _c : {}; 255 this._strokeMoveUpdate = this.throttle 256 ? throttle(SignaturePad.prototype._strokeUpdate, this.throttle) 257 : SignaturePad.prototype._strokeUpdate; 258 this._ctx = canvas.getContext('2d', this.canvasContextOptions); 259 this.clear(); 260 this.on(); 261 } 262 clear() { 263 const { _ctx: ctx, canvas } = this; 264 ctx.fillStyle = this.backgroundColor; 265 ctx.clearRect(0, 0, canvas.width, canvas.height); 266 ctx.fillRect(0, 0, canvas.width, canvas.height); 267 this._data = []; 268 this._reset(this._getPointGroupOptions()); 269 this._isEmpty = true; 270 } 271 fromDataURL(dataUrl, options = {}) { 272 return new Promise((resolve, reject) => { 273 const image = new Image(); 274 const ratio = options.ratio || window.devicePixelRatio || 1; 275 const width = options.width || this.canvas.width / ratio; 276 const height = options.height || this.canvas.height / ratio; 277 const xOffset = options.xOffset || 0; 278 const yOffset = options.yOffset || 0; 279 this._reset(this._getPointGroupOptions()); 280 image.onload = () => { 281 this._ctx.drawImage(image, xOffset, yOffset, width, height); 282 resolve(); 283 }; 284 image.onerror = (error) => { 285 reject(error); 286 }; 287 image.crossOrigin = 'anonymous'; 288 image.src = dataUrl; 289 this._isEmpty = false;
290 }); 291 } 292 toDataURL(type = 'image/png', encoderOptions) { 293 switch (type) { 294 case 'image/svg+xml': 295 if (typeof encoderOptions !== 'object') { 296 encoderOptions = undefined; 297 } 298 return `data:image/svg+xml;base64,${btoa(this.toSVG(encoderOptions))}`; 299 default: 300 if (typeof encoderOptions !== 'number') { 301 encoderOptions = undefined; 302 } 303 return this.canvas.toDataURL(type, encoderOptions); 304 } 305 } 306 on() { 307 this.canvas.style.touchAction = 'none'; 308 this.canvas.style.msTouchAction = 'none'; 309 this.canvas.style.userSelect = 'none'; 310 const isIOS = /Macintosh/.test(navigator.userAgent) && 'ontouchstart' in document; 311 if (window.PointerEvent && !isIOS) { 312 this._handlePointerEvents(); 313 } 314 else { 315 this._handleMouseEvents(); 316 if ('ontouchstart' in window) { 317 this._handleTouchEvents(); 318 } 319 } 320 } 321 off() { 322 this.canvas.style.touchAction = 'auto'; 323 this.canvas.style.msTouchAction = 'auto'; 324 this.canvas.style.userSelect = 'auto'; 325 this.canvas.removeEventListener('pointerdown', this._handlePointerDown); 326 this.canvas.removeEventListener('mousedown', this._handleMouseDown); 327 this.canvas.removeEventListener('touchstart', this._handleTouchStart); 328 this._removeMoveUpEventListeners(); 329 } 330 _getListenerFunctions() { 331 var _a; 332 const canvasWindow = window.document === this.canvas.ownerDocument 333 ? window 334 : (_a = this.canvas.ownerDocument.defaultView) !== null && _a !== void 0 ? _a : this.canvas.ownerDocument; 335 return { 336 addEventListener: canvasWindow.addEventListener.bind(canvasWindow), 337 removeEventListener: canvasWindow.removeEventListener.bind(canvasWindow), 338 }; 339 } 340 _removeMoveUpEventListeners() { 341 const { removeEventListener } = this._getListenerFunctions(); 342 removeEventListener('pointermove', this._handlePointerMove); 343 removeEventListener('pointerup', this._handlePointerUp); 344 removeEventListener('mousemove', this._handleMouseMove); 345 removeEventListener('mouseup', this._handleMouseUp); 346 removeEventListener('touchmove', this._handleTouchMove); 347 removeEventListener('touchend', this._handleTouchEnd); 348 } 349 isEmpty() { 350 return this._isEmpty; 351 } 352 fromData(pointGroups, { clear = true } = {}) { 353 if (clear) { 354 this.clear(); 355 } 356 this._fromData(pointGroups, this._drawCurve.bind(this), this._drawDot.bind(this)); 357 this._data = this._data.concat(pointGroups); 358 } 359 toData() { 360 return this._data; 361 } 362 _isLeftButtonPressed(event, only) { 363 if (only) { 364 return event.buttons === 1; 365 } 366 return (event.buttons & 1) === 1; 367 } 368 _pointerEventToSignatureEvent(event) { 369 return { 370 event: event, 371 type: event.type, 372 x: event.clientX, 373 y: event.clientY, 374 pressure: 'pressure' in event ? event.pressure : 0, 375 }; 376 } 377 _touchEventToSignatureEvent(event) { 378 const touch = event.changedTouches[0]; 379 return { 380 event: event, 381 type: event.type, 382 x: touch.clientX, 383 y: touch.clientY, 384 pressure: touch.force, 385 }; 386 } 387 _getPointGroupOptions(group) { 388 return { 389 penColor: group && 'penColor' in group ? group.penColor : this.penColor, 390 dotSize: group && 'dotSize' in group ? group.dotSize : this.dotSize, 391 minWidth: group && 'minWidth' in group ? group.minWidth : this.minWidth, 392 maxWidth: group && 'maxWidth' in group ? group.maxWidth : this.maxWidth, 393 velocityFilterWeight: group && 'velocityFilterWeight' in group 394 ? group.velocityFilterWeight 395 : this.velocityFilterWeight, 396 compositeOperation: group && 'compositeOperation' in group 397 ? group.compositeOperation 398 : this.compositeOperation, 399 }; 400 } 401 _strokeBegin(event) { 402 const cancelled = !this.dispatchEvent(new CustomEvent('beginStroke', { detail: event, cancelable: true })); 403 if (cancelled) { 404 return; 405 } 406 const { addEventListener } = this._getListenerFunctions(); 407 switch (event.event.type) { 408 case 'mousedown': 409 addEventListener('mousemove', this._handleMouseMove); 410 addEventListener('mouseup', this._handleMouseUp); 411 break; 412 case 'touchstart': 413 addEventListener('touchmove', this._handleTouchMove); 414 addEventListener('touchend', this._handleTouchEnd); 415 break; 416 case 'pointerdown': 417 addEventListener('pointermove', this._handlePointerMove); 418 addEventListener('pointerup', this._handlePointerUp); 419 break; 420 } 421 this._drawingStroke = true; 422 const pointGroupOptions = this._getPointGroupOptions(); 423 const newPointGroup = Object.assign(Object.assign({}, pointGroupOptions), { points: [] }); 424 this._data.push(newPointGroup); 425 this._reset(pointGroupOptions); 426 this._strokeUpdate(event); 427 } 428 _strokeUpdate(event) { 429 if (!this._drawingStroke) { 430 return; 431 } 432 if (this._data.length === 0) { 433 this._strokeBegin(event); 434 return; 435 } 436 this.dispatchEvent(new CustomEvent('beforeUpdateStroke', { detail: event })); 437 const point = this._createPoint(event.x, event.y, event.pressure); 438 const lastPointGroup = this._data[this._data.length - 1]; 439 const lastPoints = lastPointGroup.points; 440 const lastPoint = lastPoints.length > 0 && lastPoints[lastPoints.length - 1]; 441 const isLastPointTooClose = lastPoint 442 ? point.distanceTo(lastPoint) <= this.minDistance 443 : false;
vendor: 9,004 bytes, lines 444-644
444 const pointGroupOptions = this._getPointGroupOptions(lastPointGroup); 445 if (!lastPoint || !(lastPoint && isLastPointTooClose)) { 446 const curve = this._addPoint(point, pointGroupOptions); 447 if (!lastPoint) { 448 this._drawDot(point, pointGroupOptions); 449 } 450 else if (curve) { 451 this._drawCurve(curve, pointGroupOptions); 452 } 453 lastPoints.push({ 454 time: point.time, 455 x: point.x, 456 y: point.y, 457 pressure: point.pressure, 458 }); 459 } 460 this.dispatchEvent(new CustomEvent('afterUpdateStroke', { detail: event })); 461 } 462 _strokeEnd(event, shouldUpdate = true) { 463 this._removeMoveUpEventListeners(); 464 if (!this._drawingStroke) { 465 return; 466 } 467 if (shouldUpdate) { 468 this._strokeUpdate(event); 469 } 470 this._drawingStroke = false; 471 this.dispatchEvent(new CustomEvent('endStroke', { detail: event })); 472 } 473 _handlePointerEvents() { 474 this._drawingStroke = false; 475 this.canvas.addEventListener('pointerdown', this._handlePointerDown); 476 } 477 _handleMouseEvents() { 478 this._drawingStroke = false; 479 this.canvas.addEventListener('mousedown', this._handleMouseDown); 480 } 481 _handleTouchEvents() { 482 this.canvas.addEventListener('touchstart', this._handleTouchStart); 483 } 484 _reset(options) { 485 this._lastPoints = []; 486 this._lastVelocity = 0; 487 this._lastWidth = (options.minWidth + options.maxWidth) / 2; 488 this._ctx.fillStyle = options.penColor; 489 this._ctx.globalCompositeOperation = options.compositeOperation; 490 } 491 _createPoint(x, y, pressure) { 492 const rect = this.canvas.getBoundingClientRect(); 493 return new Point(x - rect.left, y - rect.top, pressure, new Date().getTime()); 494 } 495 _addPoint(point, options) { 496 const { _lastPoints } = this; 497 _lastPoints.push(point); 498 if (_lastPoints.length > 2) { 499 if (_lastPoints.length === 3) { 500 _lastPoints.unshift(_lastPoints[0]); 501 } 502 const widths = this._calculateCurveWidths(_lastPoints[1], _lastPoints[2], options); 503 const curve = Bezier.fromPoints(_lastPoints, widths); 504 _lastPoints.shift(); 505 return curve; 506 } 507 return null; 508 } 509 _calculateCurveWidths(startPoint, endPoint, options) { 510 const velocity = options.velocityFilterWeight * endPoint.velocityFrom(startPoint) + 511 (1 - options.velocityFilterWeight) * this._lastVelocity; 512 const newWidth = this._strokeWidth(velocity, options); 513 const widths = { 514 end: newWidth, 515 start: this._lastWidth, 516 }; 517 this._lastVelocity = velocity; 518 this._lastWidth = newWidth; 519 return widths; 520 } 521 _strokeWidth(velocity, options) { 522 return Math.max(options.maxWidth / (velocity + 1), options.minWidth); 523 } 524 _drawCurveSegment(x, y, width) { 525 const ctx = this._ctx; 526 ctx.moveTo(x, y); 527 ctx.arc(x, y, width, 0, 2 * Math.PI, false); 528 this._isEmpty = false; 529 } 530 _drawCurve(curve, options) { 531 const ctx = this._ctx; 532 const widthDelta = curve.endWidth - curve.startWidth; 533 const drawSteps = Math.ceil(curve.length()) * 2; 534 ctx.beginPath(); 535 ctx.fillStyle = options.penColor; 536 for (let i = 0; i < drawSteps; i += 1) { 537 const t = i / drawSteps; 538 const tt = t * t; 539 const ttt = tt * t; 540 const u = 1 - t; 541 const uu = u * u; 542 const uuu = uu * u; 543 let x = uuu * curve.startPoint.x; 544 x += 3 * uu * t * curve.control1.x; 545 x += 3 * u * tt * curve.control2.x; 546 x += ttt * curve.endPoint.x; 547 let y = uuu * curve.startPoint.y; 548 y += 3 * uu * t * curve.control1.y; 549 y += 3 * u * tt * curve.control2.y; 550 y += ttt * curve.endPoint.y; 551 const width = Math.min(curve.startWidth + ttt * widthDelta, options.maxWidth); 552 this._drawCurveSegment(x, y, width); 553 } 554 ctx.closePath(); 555 ctx.fill(); 556 } 557 _drawDot(point, options) { 558 const ctx = this._ctx; 559 const width = options.dotSize > 0 560 ? options.dotSize 561 : (options.minWidth + options.maxWidth) / 2; 562 ctx.beginPath(); 563 this._drawCurveSegment(point.x, point.y, width); 564 ctx.closePath(); 565 ctx.fillStyle = options.penColor; 566 ctx.fill(); 567 } 568 _fromData(pointGroups, drawCurve, drawDot) { 569 for (const group of pointGroups) { 570 const { points } = group; 571 const pointGroupOptions = this._getPointGroupOptions(group); 572 if (points.length > 1) { 573 for (let j = 0; j < points.length; j += 1) { 574 const basicPoint = points[j]; 575 const point = new Point(basicPoint.x, basicPoint.y, basicPoint.pressure, basicPoint.time); 576 if (j === 0) { 577 this._reset(pointGroupOptions); 578 } 579 const curve = this._addPoint(point, pointGroupOptions); 580 if (curve) { 581 drawCurve(curve, pointGroupOptions); 582 } 583 } 584 } 585 else { 586 this._reset(pointGroupOptions); 587 drawDot(points[0], pointGroupOptions); 588 } 589 } 590 } 591 toSVG({ includeBackgroundColor = false } = {}) { 592 const pointGroups = this._data; 593 const ratio = Math.max(window.devicePixelRatio || 1, 1); 594 const minX = 0; 595 const minY = 0; 596 const maxX = this.canvas.width / ratio; 597 const maxY = this.canvas.height / ratio; 598 const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); 599 svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg'); 600 svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); 601 svg.setAttribute('viewBox', `${minX} ${minY} ${maxX} ${maxY}`); 602 svg.setAttribute('width', maxX.toString()); 603 svg.setAttribute('height', maxY.toString()); 604 if (includeBackgroundColor && this.backgroundColor) { 605 const rect = document.createElement('rect'); 606 rect.setAttribute('width', '100%'); 607 rect.setAttribute('height', '100%'); 608 rect.setAttribute('fill', this.backgroundColor); 609 svg.appendChild(rect); 610 } 611 this._fromData(pointGroups, (curve, { penColor }) => { 612 const path = document.createElement('path'); 613 if (!isNaN(curve.control1.x) && 614 !isNaN(curve.control1.y) && 615 !isNaN(curve.control2.x) && 616 !isNaN(curve.control2.y)) { 617 const attr = `M ${curve.startPoint.x.toFixed(3)},${curve.startPoint.y.toFixed(3)} ` + 618 `C ${curve.control1.x.toFixed(3)},${curve.control1.y.toFixed(3)} ` + 619 `${curve.control2.x.toFixed(3)},${curve.control2.y.toFixed(3)} ` + 620 `${curve.endPoint.x.toFixed(3)},${curve.endPoint.y.toFixed(3)}`; 621 path.setAttribute('d', attr); 622 path.setAttribute('stroke-width', (curve.endWidth * 2.25).toFixed(3)); 623 path.setAttribute('stroke', penColor); 624 path.setAttribute('fill', 'none'); 625 path.setAttribute('stroke-linecap', 'round'); 626 svg.appendChild(path); 627 } 628 }, (point, { penColor, dotSize, minWidth, maxWidth }) => { 629 const circle = document.createElement('circle'); 630 const size = dotSize > 0 ? dotSize : (minWidth + maxWidth) / 2; 631 circle.setAttribute('r', size.toString()); 632 circle.setAttribute('cx', point.x.toString()); 633 circle.setAttribute('cy', point.y.toString()); 634 circle.setAttribute('fill', penColor); 635 svg.appendChild(circle); 636 }); 637 return svg.outerHTML; 638 } 639 } 640 641 return SignaturePad; 642 643})); 644//# sourceMappingURL=signature_pad.umd.js.map
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.