estoy desarrollando una pequeña web para que los trabajadores de una empresa que no trabajan en la oficina puedan rellenar los partes de trabajo desde el móvil. Los usuarios rellenan un formulario y con fpdf creo un informe.
El tema es que necesito poder firmar los partes de trabajo, Javascript se me da fatal, pero he encontrado que mediante Canvas se puede hacer, hay diversos ejemplos si buscas, el problema es que casi todos son para ratón (desde pc) y no para dedo (móvil o tablet) y lo poco que he encontrado para dedo son ejemplos supersencillos que no guardarla imagen y necesito guardarla en una carpeta de mi servidor
Encontré el siguiente código que es genial por que te permite firmar tanto con el dedo como con el ratón, el problema es que no guarda la imagen en el servidor sino que la descarga.
He intentado modificar el código para guardar en el servidor, pero no lo consigo, si alguien me puede echar una mano me haría un gran favor.
Html:
Código:
Javascript Funciones (ESTE ES EL QUE INTENTO MODIFICAR)<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Firma</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"> <!--[if IE]> <link rel="stylesheet" type="text/css" href="css/ie9.css"> <![endif]--> <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"> <div id="signature-pad" class="signature-pad"> <div class="signature-pad--body"> <canvas></canvas> </div> <div class="signature-pad--footer"> <div class="description">Sign above</div> <div class="signature-pad--actions"> <div> <button type="button" class="button clear" data-action="clear">Limpiar</button> <button type="button" class="button" data-action="change-color">Cambiar color</button> <button type="button" class="button" data-action="undo">Atras</button> </div> <div> <button type="button" class="button save" data-action="save-png">Salvar como PNG</button> <button type="button" class="button save" data-action="save-jpg">Salvar como JPG</button> <button type="button" class="button save" data-action="save-svg">Salvar como SVG</button> </div> </div> </div> </div> <script src="js/signature_pad.umd.js"></script> <script src="js/app.js"></script> </body> </html>
Código:
Falta el scrip que controla el liezo y el css, si alguien lo necesita se lo puedo facilitarvar wrapper = document.getElementById("signature-pad"); var clearButton = wrapper.querySelector("[data-action=clear]"); var changeColorButton = wrapper.querySelector("[data-action=change-color]"); var undoButton = wrapper.querySelector("[data-action=undo]"); var savePNGButton = wrapper.querySelector("[data-action=save-png]"); var saveJPGButton = wrapper.querySelector("[data-action=save-jpg]"); var saveSVGButton = wrapper.querySelector("[data-action=save-svg]"); var canvas = wrapper.querySelector("canvas"); var 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)' }); // 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. var 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(); } // On mobile devices it might make more sense to listen to orientation change, // rather than window resize events. window.onresize = resizeCanvas; resizeCanvas(); function download(dataURL, filename) { if (navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1) { window.open(dataURL); } else { var blob = dataURLToBlob(dataURL); var url = window.URL.createObjectURL(blob); var 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 var parts = dataURL.split(';base64,'); var contentType = parts[0].split(":")[1]; var raw = window.atob(parts[1]); var rawLength = raw.length; var uInt8Array = new Uint8Array(rawLength); for (var i = 0; i < rawLength; ++i) { uInt8Array[i] = raw.charCodeAt(i); } return new Blob([uInt8Array], { type: contentType }); } clearButton.addEventListener("click", function (event) { signaturePad.clear(); }); undoButton.addEventListener("click", function (event) { var data = signaturePad.toData(); if (data) { data.pop(); // remove the last dot or line signaturePad.fromData(data); } }); changeColorButton.addEventListener("click", function (event) { var r = Math.round(Math.random() * 255); var g = Math.round(Math.random() * 255); var b = Math.round(Math.random() * 255); var color = "rgb(" + r + "," + g + "," + b +")"; signaturePad.penColor = color; }); savePNGButton.addEventListener("click", function (event) { if (signaturePad.isEmpty()) { alert("Please provide a signature first."); } else { var dataURL = signaturePad.toDataURL(); download(dataURL, "signature.png"); } }); saveJPGButton.addEventListener("click", function (event) { if (signaturePad.isEmpty()) { alert("Please provide a signature first."); } else { var dataURL = signaturePad.toDataURL("image/jpeg"); download(dataURL, "signature.jpg"); } }); saveSVGButton.addEventListener("click", function (event) { if (signaturePad.isEmpty()) { alert("Please provide a signature first."); } else { var dataURL = signaturePad.toDataURL('image/svg+xml'); download(dataURL, "signature.svg"); } });
Ejemplo en funcionamiento:
http://grupseven.com/informes/firma4/
Código que guarda la imagen en el servidor y que he intentado añadir, substituyendo la función download
javascript:
Código:
Php(snapshot.php):function sendToServer() { var data = canvas.toDataURL('image/png'); var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { // request complete if (xhr.readyState == 4) { window.open('http://www.miweb.com/snapshots/'+xhr.responseText,'_blank'); } } xhr.open('POST','http://www.miweb.com/snapshot.php',true); xhr.setRequestHeader('Content-Type', 'application/upload'); xhr.send(data); }
Código:
Gracias de antemano por la ayuda! <?php // read input stream $data = file_get_contents("php://input"); // filtering and decoding code adapted from // http://stackoverflow.com/questions/11843115/uploading-canvas-context-as-image-using-ajax-and-php?lq=1 // Filter out the headers (data:,) part. $filteredData=substr($data, strpos($data, ",")+1); // Need to decode before saving since the data we received is already base64 encoded $decodedData=base64_decode($filteredData); // store in server $fic_name = 'snapshot'.rand(1000,9999).'.png'; $fp = fopen('./snapshots/'.$fic_name, 'wb'); $ok = fwrite( $fp, $decodedData); fclose( $fp ); if($ok) echo $fic_name; else echo "ERROR"; ?>