avances en plantillas

This commit is contained in:
JACS 2026-05-01 18:15:40 -05:00
parent 0f84beacf1
commit da0530d79b
2062 changed files with 598814 additions and 22 deletions

View file

@ -0,0 +1,5 @@
module.exports = {
globals: {
SignaturePad: false
}
};

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,73 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Signature Pad demo</title>
<meta name="description"
content="Signature Pad - HTML5 canvas based smooth signature drawing using variable width spline interpolation.">
<meta name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" href="css/signature-pad.css">
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-39365077-1']);
_gaq.push(['_trackPageview']);
(function () {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body onselectstart="return false">
<span id="forkongithub">
<a href="https://github.com/szimek/signature_pad">Fork me on GitHub</a>
</span>
<div id="signature-pad" class="signature-pad">
<div id="canvas-wrapper" class="signature-pad--body">
<canvas></canvas>
</div>
<div class="signature-pad--footer">
<div class="description">Sign above</div>
<div class="signature-pad--actions">
<div class="column">
<button type="button" class="button clear" data-action="clear">Clear</button>
<button type="button" class="button" data-action="undo" title="Ctrl-Z">Undo</button>
<button type="button" class="button" data-action="redo" title="Ctrl-Y">Redo</button>
<br/>
<button type="button" class="button" data-action="change-color">Change color</button>
<button type="button" class="button" data-action="change-width">Change width</button>
<button type="button" class="button" data-action="change-background-color">Change background color</button>
</div>
<div class="column">
<button type="button" class="button save" data-action="save-png">Save as PNG</button>
<button type="button" class="button save" data-action="save-jpg">Save as JPG</button>
<button type="button" class="button save" data-action="save-svg">Save as SVG</button>
<button type="button" class="button save" data-action="save-svg-with-background">Save as SVG with
background</button>
</div>
</div>
<div>
<button type="button" class="button" data-action="open-in-window">Open in Window</button>
</div>
</div>
</div>
<script src="js/signature_pad.umd.min.js"></script>
<script src="js/app.js"></script>
</body>
</html>

View file

@ -0,0 +1,198 @@
const wrapper = document.getElementById("signature-pad");
const canvasWrapper = document.getElementById("canvas-wrapper");
const clearButton = wrapper.querySelector("[data-action=clear]");
const changeBackgroundColorButton = wrapper.querySelector("[data-action=change-background-color]");
const changeColorButton = wrapper.querySelector("[data-action=change-color]");
const changeWidthButton = wrapper.querySelector("[data-action=change-width]");
const undoButton = wrapper.querySelector("[data-action=undo]");
const redoButton = wrapper.querySelector("[data-action=redo]");
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 saveSVGWithBackgroundButton = wrapper.querySelector("[data-action=save-svg-with-background]");
const openInWindowButton = wrapper.querySelector("[data-action=open-in-window]");
let undoData = [];
const canvas = wrapper.querySelector("canvas");
const signaturePad = new SignaturePad(canvas, {
// It's Necessary to use an opaque color when saving image as JPEG;
// this option can be omitted if only saving as PNG or SVG
backgroundColor: 'rgb(255, 255, 255)'
});
function randomColor() {
const r = Math.round(Math.random() * 255);
const g = Math.round(Math.random() * 255);
const b = Math.round(Math.random() * 255);
return `rgb(${r},${g},${b})`;
}
// Adjust canvas coordinate space taking into account pixel ratio,
// to make it look crisp on mobile devices.
// This also causes canvas to be cleared.
function resizeCanvas() {
// When zoomed out to less than 100%, for some very strange reason,
// some browsers report devicePixelRatio as less than 1
// and only part of the canvas is cleared then.
const ratio = Math.max(window.devicePixelRatio || 1, 1);
// This part causes the canvas to be cleared
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
// This library does not listen for canvas changes, so after the canvas is automatically
// cleared by the browser, SignaturePad#isEmpty might still return false, even though the
// canvas looks empty, because the internal data of this library wasn't cleared. To make sure
// that the state of this library is consistent with visual state of the canvas, you
// have to clear it manually.
//signaturePad.clear();
// If you want to keep the drawing on resize instead of clearing it you can reset the data.
signaturePad.redraw();
}
// On mobile devices it might make more sense to listen to orientation change,
// rather than window resize events.
window.onresize = resizeCanvas;
resizeCanvas();
window.addEventListener("keydown", (event) => {
switch (true) {
case event.key === "z" && event.ctrlKey:
undoButton.click();
break;
case event.key === "y" && event.ctrlKey:
redoButton.click();
break;
}
});
function download(dataURL, filename) {
const blob = dataURLToBlob(dataURL);
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.style = "display: none";
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
}
// One could simply use Canvas#toBlob method instead, but it's just to show
// that it can be done using result of SignaturePad#toDataURL.
function dataURLToBlob(dataURL) {
// Code taken from https://github.com/ebidel/filer.js
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 (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}
signaturePad.addEventListener("endStroke", () => {
// clear undoData when new data is added
undoData = [];
});
clearButton.addEventListener("click", () => {
signaturePad.clear();
});
undoButton.addEventListener("click", () => {
const data = signaturePad.toData();
if (data && data.length > 0) {
// remove the last dot or line
const removed = data.pop();
undoData.push(removed);
signaturePad.redraw();
}
});
redoButton.addEventListener("click", () => {
if (undoData.length > 0) {
const data = signaturePad.toData();
data.push(undoData.pop());
signaturePad.redraw();
}
});
changeBackgroundColorButton.addEventListener("click", () => {
signaturePad.backgroundColor = randomColor();
signaturePad.redraw();
});
changeColorButton.addEventListener("click", () => {
signaturePad.penColor = randomColor();
});
changeWidthButton.addEventListener("click", () => {
const min = Math.round(Math.random() * 100) / 10;
const max = Math.round(Math.random() * 100) / 10;
signaturePad.minWidth = Math.min(min, max);
signaturePad.maxWidth = Math.max(min, max);
});
savePNGButton.addEventListener("click", () => {
if (signaturePad.isEmpty()) {
alert("Please provide a signature first.");
} else {
const dataURL = signaturePad.toDataURL();
download(dataURL, "signature.png");
}
});
saveJPGButton.addEventListener("click", () => {
if (signaturePad.isEmpty()) {
alert("Please provide a signature first.");
} else {
const dataURL = signaturePad.toDataURL("image/jpeg");
download(dataURL, "signature.jpg");
}
});
saveSVGButton.addEventListener("click", () => {
if (signaturePad.isEmpty()) {
alert("Please provide a signature first.");
} else {
const dataURL = signaturePad.toDataURL('image/svg+xml');
download(dataURL, "signature.svg");
}
});
saveSVGWithBackgroundButton.addEventListener("click", () => {
if (signaturePad.isEmpty()) {
alert("Please provide a signature first.");
} else {
const dataURL = signaturePad.toDataURL('image/svg+xml', { includeBackgroundColor: true, includeDataUrl: true });
download(dataURL, "signature.svg");
}
});
openInWindowButton.addEventListener("click", () => {
var externalWin = window.open('', '', `width=${canvas.width / window.devicePixelRatio},height=${canvas.height / window.devicePixelRatio}`);
canvas.style.width = "100%";
canvas.style.height = "100%";
externalWin.onresize = resizeCanvas;
externalWin.document.body.style.margin = '0';
externalWin.document.body.appendChild(canvas);
canvasWrapper.classList.add("empty");
externalWin.onbeforeunload = () => {
canvas.style.width = "";
canvas.style.height = "";
canvasWrapper.classList.remove("empty");
canvasWrapper.appendChild(canvas);
resizeCanvas();
};
})

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long