From 69b2701fbfeea7eb054721b042157894052003d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Sz=C3=BCcs?= <127139797+balazs-szucs@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:46:26 +0200 Subject: [PATCH] feat(sign): Add signature color picker and custom signature colors (#4441) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description of Changes Added sign custom colour as per #4413 ### Example doc [lorem-ipsum_signed.pdf](https://github.com/user-attachments/files/22310651/lorem-ipsum_signed.pdf) ### UI/Picture image image image Closes #4413 --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [x] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Signed-off-by: Balázs Szücs Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com> --- .../main/resources/messages_en_GB.properties | 1 + .../src/main/resources/static/css/sign.css | 16 +++++++++++++++ .../main/resources/static/js/pages/sign.js | 20 ++++++++++++++++++- .../static/js/sign/signature-canvas.js | 18 ++++++++++++++--- .../src/main/resources/templates/sign.html | 13 ++++++++++-- 5 files changed, 62 insertions(+), 6 deletions(-) diff --git a/app/core/src/main/resources/messages_en_GB.properties b/app/core/src/main/resources/messages_en_GB.properties index 0a58ddc26..1859c4868 100644 --- a/app/core/src/main/resources/messages_en_GB.properties +++ b/app/core/src/main/resources/messages_en_GB.properties @@ -1233,6 +1233,7 @@ sign.previous=Previous page sign.maintainRatio=Toggle maintain aspect ratio sign.undo=Undo sign.redo=Redo +sign.colour=Signature Colour #repair repair.title=Repair diff --git a/app/core/src/main/resources/static/css/sign.css b/app/core/src/main/resources/static/css/sign.css index 39ea4c9be..0b1524e07 100644 --- a/app/core/src/main/resources/static/css/sign.css +++ b/app/core/src/main/resources/static/css/sign.css @@ -10,6 +10,22 @@ select#font-select option { text-align: center; } +.signature-color-picker { + display: inline-flex; + align-items: center; + gap: 0.5rem; + margin: 0.5rem 0 0.75rem; +} + +.signature-color-picker input[type="color"] { + width: 42px; + height: 32px; + padding: 0; + border: 1px solid var(--bs-border-color, #ced4da); + border-radius: 6px; + background: transparent; +} + #drawing-pad-canvas { background: rgba(125, 125, 125, 0.2); width: 100%; diff --git a/app/core/src/main/resources/static/js/pages/sign.js b/app/core/src/main/resources/static/js/pages/sign.js index 36902aa7b..ec02e75b3 100644 --- a/app/core/src/main/resources/static/js/pages/sign.js +++ b/app/core/src/main/resources/static/js/pages/sign.js @@ -7,6 +7,12 @@ window.goToFirstOrLastPage = goToFirstOrLastPage; let currentPreviewSrc = null; +function getSelectedSignatureColor() { + const textPicker = document.getElementById('signature-color-text'); + const drawPicker = document.getElementById('signature-color'); + return (textPicker && textPicker.value) || (drawPicker && drawPicker.value) || '#000000'; +} + function toggleSignatureView() { const gridView = document.getElementById("gridView"); const listView = document.getElementById("listView"); @@ -242,9 +248,19 @@ const signaturePadCanvas = document.getElementById("drawing-pad-canvas"); const signaturePad = new SignaturePad(signaturePadCanvas, { minWidth: 1, maxWidth: 2, - penColor: "black", + penColor: "#000000", }); +// Keep pad color in sync if draw picker exists +(function initPadColorSync() { + const drawPicker = document.getElementById('signature-color'); + if (!drawPicker) return; + if (drawPicker.value) signaturePad.penColor = drawPicker.value; + drawPicker.addEventListener('input', () => { + signaturePad.penColor = drawPicker.value || '#000000'; + }); +})(); + function addDraggableFromPad() { if (signaturePad.isEmpty()) return; const startTime = Date.now(); @@ -328,6 +344,7 @@ function addDraggableFromText() { const sigText = document.getElementById("sigText").value; const font = document.querySelector("select[name=font]").value; const fontSize = 100; + const color = getSelectedSignatureColor(); const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); @@ -340,6 +357,7 @@ function addDraggableFromText() { canvas.width = textWidth; canvas.height = paragraphs.length * textHeight * 1.35; // for tails ctx.font = `${fontSize}px ${font}`; + ctx.fillStyle = color; ctx.textBaseline = "top"; diff --git a/app/core/src/main/resources/static/js/sign/signature-canvas.js b/app/core/src/main/resources/static/js/sign/signature-canvas.js index a3f7b1e90..042236d69 100644 --- a/app/core/src/main/resources/static/js/sign/signature-canvas.js +++ b/app/core/src/main/resources/static/js/sign/signature-canvas.js @@ -4,9 +4,21 @@ const redoButton = document.getElementById("signature-redo-button"); const signaturePad = new SignaturePad(signaturePadCanvas, { minWidth: 1, maxWidth: 2, - penColor: 'black', + penColor: '#000000', // default color }); +(function initSignatureColor() { + const colorInput = document.getElementById('signature-color'); + if (!colorInput) return; + + if (colorInput.value) { + signaturePad.penColor = colorInput.value; + } + colorInput.addEventListener('input', () => { + signaturePad.penColor = colorInput.value || '#000000'; + }); +})(); + let undoData = []; signaturePad.addEventListener("endStroke", () => { @@ -16,10 +28,10 @@ signaturePad.addEventListener("endStroke", () => { window.addEventListener("keydown", (event) => { switch (true) { case event.key === "z" && event.ctrlKey: - undoButton.click(); + undoButton?.click(); break; case event.key === "y" && event.ctrlKey: - redoButton.click(); + redoButton?.click(); break; } }); diff --git a/app/core/src/main/resources/templates/sign.html b/app/core/src/main/resources/templates/sign.html index cefb488fe..d6032db3f 100644 --- a/app/core/src/main/resources/templates/sign.html +++ b/app/core/src/main/resources/templates/sign.html @@ -50,6 +50,10 @@
+
+ + +