diff --git a/app/javascript/draw.js b/app/javascript/draw.js index a4936e8d..f8d7ca19 100644 --- a/app/javascript/draw.js +++ b/app/javascript/draw.js @@ -4,14 +4,21 @@ import { isValidSignatureCanvas } from './submission_form/validate_signature' window.customElements.define('draw-signature', class extends HTMLElement { connectedCallback () { - const scale = 3 + this.setCanvasSize() - this.canvas.width = this.canvas.parentNode.clientWidth * scale - this.canvas.height = this.canvas.parentNode.clientHeight * scale + this.pad = new SignaturePad(this.canvas) - this.canvas.getContext('2d').scale(scale, scale) + this.resizeObserver = new ResizeObserver(() => { + const { width, height } = this.canvas - this.pad = new SignaturePad(this.canvas) + this.setCanvasSize() + + if (this.canvas.width !== width || this.canvas.height !== height) { + this.redrawCanvas(width, height) + } + }) + + this.resizeObserver.observe(this.canvas.parentNode) if (this.dataset.color) { this.pad.penColor = this.dataset.color @@ -57,6 +64,40 @@ window.customElements.define('draw-signature', class extends HTMLElement { this.updateSubmitButtonVisibility() } + disconnectedCallback () { + if (this.resizeObserver) { + this.resizeObserver.disconnect() + } + } + + setCanvasSize () { + const scale = 3 + + const width = this.canvas.parentNode.clientWidth + const height = this.canvas.parentNode.clientHeight + + if (this.canvas.width !== width * scale || this.canvas.height !== height * scale) { + this.canvas.width = width * scale + this.canvas.height = height * scale + + this.canvas.getContext('2d').scale(scale, scale) + } + } + + redrawCanvas (oldWidth, oldHeight) { + if (this.pad && !this.pad.isEmpty()) { + const sx = this.canvas.width / oldWidth + const sy = this.canvas.height / oldHeight + + const scaledData = this.pad.toData().map((stroke) => ({ + ...stroke, + points: stroke.points.map((p) => ({ ...p, x: p.x * sx, y: p.y * sy })) + })) + + this.pad.fromData(scaledData) + } + } + updateSubmitButtonVisibility () { if (this.pad.isEmpty()) { this.submitButton.style.display = 'none' diff --git a/app/javascript/elements/signature_form.js b/app/javascript/elements/signature_form.js index 55020081..d4305adc 100644 --- a/app/javascript/elements/signature_form.js +++ b/app/javascript/elements/signature_form.js @@ -5,16 +5,23 @@ export default targetable(class extends HTMLElement { static [target.static] = ['canvas', 'input', 'clear', 'button'] async connectedCallback () { - const scale = 3 + const { default: SignaturePad } = await import('signature_pad') + + this.setCanvasSize() - this.canvas.width = this.canvas.parentNode.clientWidth * scale - this.canvas.height = this.canvas.parentNode.clientHeight * scale + this.pad = new SignaturePad(this.canvas) - this.canvas.getContext('2d').scale(scale, scale) + this.resizeObserver = new ResizeObserver(() => { + const { width, height } = this.canvas - const { default: SignaturePad } = await import('signature_pad') + this.setCanvasSize() - this.pad = new SignaturePad(this.canvas) + if (this.canvas.width !== width || this.canvas.height !== height) { + this.redrawCanvas(width, height) + } + }) + + this.resizeObserver.observe(this.canvas.parentNode) this.clear.addEventListener('click', (e) => { e.preventDefault() @@ -47,4 +54,38 @@ export default targetable(class extends HTMLElement { this.closest('form').requestSubmit() } + + disconnectedCallback () { + if (this.resizeObserver) { + this.resizeObserver.disconnect() + } + } + + setCanvasSize () { + const scale = 3 + + const width = this.canvas.parentNode.clientWidth + const height = this.canvas.parentNode.clientWidth / 2.5 + + if (this.canvas.width !== width * scale || this.canvas.height !== height * scale) { + this.canvas.width = width * scale + this.canvas.height = height * scale + + this.canvas.getContext('2d').scale(scale, scale) + } + } + + redrawCanvas (oldWidth, oldHeight) { + if (this.pad && !this.pad.isEmpty()) { + const sx = this.canvas.width / oldWidth + const sy = this.canvas.height / oldHeight + + const scaledData = this.pad.toData().map((stroke) => ({ + ...stroke, + points: stroke.points.map((p) => ({ ...p, x: p.x * sx, y: p.y * sy })) + })) + + this.pad.fromData(scaledData) + } + } }) diff --git a/app/javascript/submission_form/signature_step.vue b/app/javascript/submission_form/signature_step.vue index 268cb6a9..d5726b67 100644 --- a/app/javascript/submission_form/signature_step.vue +++ b/app/javascript/submission_form/signature_step.vue @@ -175,9 +175,7 @@ v-if="isShowQr" class="top-0 bottom-0 right-0 left-0 absolute bg-base-content/10 rounded-2xl" > -