【问题标题】:Can't get html5 Canvas signature pad to submit to database无法获取 html5 Canvas 签名板以提交到数据库
【发布时间】:2013-06-05 15:21:16
【问题描述】:

所以我一直在寻找一个真正有效的签名捕获脚本并将签名保存到 MySQL 并且我终于找到了我想要的但有两个问题。

  1. 我不明白为什么按下清除按钮时画布不会清除签名。

  2. 当保存签名按钮被按下时,它不会将图像提交给 MySQL。

这段代码已经很老了,我试图联系开发人员,但没有得到回复,所以我希望我能在这里得到一些帮助。

这里是html:

        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">

    <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Signature Pad</title>
    <script type="text/javascript" src="jquery.min.js"></script>
    </head>
    <body>
    <center>
        <fieldset style="width: 435px">
            <br/>
            <br/>
            <div id="signaturePad" style="border: 1px solid #ccc; height: 55px; width: 400px;"></div>
            <br/>
            <button id="clearSig" type="button">Clear Signature</button>&nbsp;
            <button id="saveSig" type="button">Save Signature</button>
            <div id="imgData"></div>
            <div id="imgData"></div>
            <br/>
            <br/>
        </fieldset>
    </center>
    </body>
    </html>

还有剩下的 php 和脚本:

    $(document).ready(function () {
    /** Set Canvas Size **/
    var canvasWidth = 400;
    var canvasHeight = 75;

    /** IE SUPPORT **/
    var canvasDiv = document.getElementById('signaturePad');
    canvas = document.createElement('canvas');
    canvas.setAttribute('width', canvasWidth);
    canvas.setAttribute('height', canvasHeight);
    canvas.setAttribute('id', 'canvas');
    canvasDiv.appendChild(canvas);
    if (typeof G_vmlCanvasManager != 'undefined') {
        canvas = G_vmlCanvasManager.initElement(canvas);
    }
    context = canvas.getContext("2d");

    var clickX = new Array();
    var clickY = new Array();
    var clickDrag = new Array();
    var paint;

    /** Redraw the Canvas **/
    function redraw() {
        canvas.width = canvas.width; // Clears the canvas

        context.strokeStyle = "#000000";
        context.lineJoin = "miter";
        context.lineWidth = 2;

        for (var i = 0; i < clickX.length; i++) {
            context.beginPath();
            if (clickDrag[i] && i) {
                context.moveTo(clickX[i - 1], clickY[i - 1]);
            } else {
                context.moveTo(clickX[i] - 1, clickY[i]);
            }
            context.lineTo(clickX[i], clickY[i]);
            context.closePath();
            context.stroke();
        }
    }

    /** Save Canvas **/
    $("#saveSig").click(function saveSig() {
        var sigData = canvas.toDataURL("image/png");
        $("#imgData").html('Thank you! Your signature was saved');
        var ajax = XMLHttpRequest();
        ajax.open("POST", 'http://www.your-domain.com/folder/post-html.php');
        ajax.setRequestHeader('Content-Type', 'application/upload');
        ajax.send(sigData);
    });

    /** Clear Canvas **/
    function clearSig() {
        clickX = new Array();
        clickY = new Array();
        clickDrag = new Array();
        canvas.width = canvas.width;
        canvas.height = canvas.height;
    }

    /**Draw when moving over Canvas **/
    $('#signaturePad').mousemove(function (e) {
        if (paint) {
            addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
            redraw();
        }
    });

    /**Stop Drawing on Mouseup **/
    $('#signaturePad').mouseup(function (e) {
        paint = false;
    });

    /** Starting a Click **/
    function addClick(x, y, dragging) {
        clickX.push(x);
        clickY.push(y);
        clickDrag.push(dragging);
    }

    $('#signaturePad').mousedown(function (e) {
        var mouseX = e.pageX - this.offsetLeft;
        var mouseY = e.pageY - this.offsetTop;

        paint = true;
        addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
        redraw();
    });

});

MySQL 部分:

    <?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
$session_id = $_SERVER['REMOTE_ADDR'];
// Get the data
$imageData=$GLOBALS['HTTP_RAW_POST_DATA'];

// Remove the headers (data:,) part.
// A real application should use them according to needs such as to check image type
$filteredData=substr($imageData, strpos($imageData, ",")+1);

// Need to decode before saving since the data we received is already base64 encoded
$unencodedData=base64_decode($filteredData);

//echo "unencodedData".$unencodedData;
$imageName = "sign_" . rand(5,1000) . rand(1, 10) . rand(10000, 150000) . rand(1500, 100000000) . ".png";
//Set the absolute path to your folder (i.e. /usr/home/your-domain/your-folder/
$filepath = "htdocs/alpha/site6/signature/images/" . $imageName;

$fp = fopen("$filepath", 'wb' );
fwrite( $fp, $unencodedData);
fclose( $fp );

//Connect to a mySQL database and store the user's information so you can link to it later
$link = mysql_connect('localhost','root', 'pwd') OR DIE(mysql_error);
mysql_select_db("trial", $link);
mysql_query("INSERT INTO customer (`session`, `image_location`) VALUES ('$session_id', '$imageName')") OR DIE(mysql_error());
mysql_close($link);
}
?>

【问题讨论】:

  • 这段代码有很多东西。但是对于清除签名,您需要为单击按钮添加一个处理程序以实际调用清除函数。设置canvas.width = canvas.width 是一种技巧,并非在所有浏览器中都有效。请改用ctx.clearRect(0, 0, canvas.width, canvas.height)。保存签名的代码在此代码中加倍..
  • @Ken-AbdiasSoftware 如果我理解正确,我删除了 canvas.width 和 canvas.heigh 并替换为 ctx.clearRect 并在 onClick="clearSig 的清除按钮上添加了一个处理程序()" 如果这是正确的,它仍然不会清除画布。我还删除了第二个保存签名代码,但它仍然不会保存到数据库中。我不确定如何处理这部分 ajax.open("POST", 'your-domain.com/folder/post-html.php'); post-html.php 是更改还是保留?
  • 好的,我添加了部分答案。
  • @Ken-AbdiasSoftware 因此添加 ctx.clearRect 代替 canvas.width 也不起作用我收到错误 ctx undefined。我把它放回原来的样子,并且分配给按钮的处理程序会清除它,但是一旦将指针放回画布上,以前的文本就会重新出现。

标签: javascript mysql ajax


【解决方案1】:

我只能给出部分答案,因为我对 PHP 部分无能为力。

我将代码放在一个 jsfiddle 中,并在此处进行了一些更正:
http://jsfiddle.net/AbdiasSoftware/M8pzB/

您可以看到清除按钮按我的建议工作(除了我在评论中使用 ctx 而不是上下文)。

我还从 HTML 中删除了一个带有双 ID 的 div (imgData)。

清除功能:

$('#clearSig').click(
    function clearSig() {
        clickX = new Array();
        clickY = new Array();
        clickDrag = new Array();
        context.clearRect(0, 0, canvas.width, canvas.height);
});

我在 HTML 中添加了一个调试标签,它显示了现在一切正常,直到您将其发送到服务器。由于我无法测试这部分,我只能建议您从该部分开始调试。

我还为从画布生成的数据 URL 添加了 URI 编码,这是必要的。

传输 MIME 可以是 text/plain,因为您传输的是字符串。由于您使用 jQuery,您可以使用内置函数进行 ajax 传输:
http://api.jquery.com/jQuery.ajax/

然后在 PHP 端解码 URI,像你一样剥离 data-url 的标头,然后如果你想将其存储为二进制文件,则对其进行 base64 解码。请注意,在 MySQL 中,您需要将其存储为 BLOB(不要与 HTML5 的 Blob 对象混淆)。

【讨论】:

  • 谢谢你,Ken 帮了大忙,修复了我最后一条关于清除后重新出现在画布中的文本的评论。至于 BlOB,我不想将图像存储在数据库中,只是将其上传到的文件夹的路径。
  • 再次感谢肯,你已经修复了很大一部分。我将检查此问题作为已回答并为数据库部分提交一个新问题,正如我在单击保存按钮时看到的那样,它传递给脚本的 POST 部分并给我一个 200 ok 代码但没有任何反应所以我很难过。再次感谢。
  • 这部分有错误:´$("#saveSig").click(function saveSig() { //encode URI var sigData = encodeURIComponent(canvas.toDataURL("image/png" )); $("#imgData").html('谢谢!您的签名已保存'); var ajax = XMLHttpRequest(); ajax.open("POST", 'sig/signature.php'); ajax. setRequestHeader('Content-Type', 'application/upload'); ajax.send(sigData); $('#debug').html(sigData); });´ 出现此错误“错误:无法构造 'XMLHttpRequest ': 请使用'new'操作符,这个DOM对象构造函数不能作为函数调用。"
猜你喜欢
  • 1970-01-01
  • 2015-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多