0

I'm trying to make a form using a box where user can draw something with the mouse. When saving the form, the drawned file must be stored and it name linked in the database.

I'm not used to canvas and i'm struggling a bit. Here is the js code part :

$(document).ready(() => {
    var canvasDiv = document.getElementById('canvasDiv');
    var canvas = document.createElement('canvas');
    canvas.setAttribute('id', 'canvas');
    canvasDiv.appendChild(canvas);
    $("#canvas").attr('height', $("#canvasDiv").outerHeight());
    $("#canvas").attr('width', $("#canvasDiv").width());
    if (typeof G_vmlCanvasManager != 'undefined') {
        canvas = G_vmlCanvasManager.initElement(canvas);
    }

    context = canvas.getContext("2d");
    $('#canvas').mousedown(function(e) {
        var offset = $(this).offset()
        var mouseX = e.pageX - this.offsetLeft;
        var mouseY = e.pageY - this.offsetTop;

        paint = true;
        addClick(e.pageX - offset.left, e.pageY - offset.top);
        redraw();
    });

    $('#canvas').mousemove(function(e) {
        if (paint) {
            var offset = $(this).offset()
            //addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
            addClick(e.pageX - offset.left, e.pageY - offset.top, true);
            console.log(e.pageX, offset.left, e.pageY, offset.top);
            redraw();
        }
    });

    $('#canvas').mouseup(function(e) {
        paint = false;
    });

    $('#canvas').mouseleave(function(e) {
        paint = false;
    });

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

    function addClick(x, y, dragging) {
        clickX.push(x);
        clickY.push(y);
        clickDrag.push(dragging);
    }

    $("#reset-btn").click(function() {
        context.clearRect(0, 0, window.innerWidth, window.innerWidth);
        clickX = [];
        clickY = [];
        clickDrag = [];
    });

    $(document).on('click', '#btn-save', function() {
        var mycanvas = document.getElementById('canvas');
        var img = mycanvas.toDataURL("image");
        window.location.assign=img;
        anchor = $("#signature");
        anchor.val(img);
        img.download = 'image.png';

        $("#signatureform").submit();

    });

    var drawing = false;
    var mousePos = {
        x: 0,
        y: 0
    };
    var lastPos = mousePos;

    canvas.addEventListener("touchstart", function(e) {
        mousePos = getTouchPos(canvas, e);
        var touch = e.touches[0];
        var mouseEvent = new MouseEvent("mousedown", {
            clientX: touch.clientX,
            clientY: touch.clientY
        });
        canvas.dispatchEvent(mouseEvent);
    }, false);


    canvas.addEventListener("touchend", function(e) {
        var mouseEvent = new MouseEvent("mouseup", {});
        canvas.dispatchEvent(mouseEvent);
    }, false);


    canvas.addEventListener("touchmove", function(e) {

        var touch = e.touches[0];
        var offset = $('#canvas').offset();
        var mouseEvent = new MouseEvent("mousemove", {
            clientX: touch.clientX,
            clientY: touch.clientY
        });
        canvas.dispatchEvent(mouseEvent);
    }, false);



    // Get the position of a touch relative to the canvas
    function getTouchPos(canvasDiv, touchEvent) {
        var rect = canvasDiv.getBoundingClientRect();
        return {
            x: touchEvent.touches[0].clientX - rect.left,
            y: touchEvent.touches[0].clientY - rect.top
        };
    }


    var elem = document.getElementById("canvas");

    var defaultPrevent = function(e) {
        e.preventDefault();
    }
    elem.addEventListener("touchstart", defaultPrevent);
    elem.addEventListener("touchmove", defaultPrevent);


    function redraw() {
        //
        lastPos = mousePos;
        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();
        }
    }
})

And here my form :

{% extends '@!EasyAdmin/layout.html.twig' %}

{% block content %}

{% for flashError in app.flashes('verify_email_error') %}
    <div class="alert alert-danger" role="alert">{{ flashError }}</div>
{% endfor %}

             {{ form_start(formWithElectroSignature) }}
<div class="form-control js-user-autocomplete" autocomplete="on">
 {{ form_label(formWithElectroSignature.personnel) }}<br>

                               {{ form_widget(formWithElectroSignature.personnel) }}

  </div>
<div class="form-control">
<i class="fa fa-calendar"></i> {{ form_label(formWithElectroSignature.dateDebut) }}<br>
              {{ form_widget(formWithElectroSignature.dateDebut) }}

  </div>
  <div class="form-control">
   {{ form_label(formWithElectroSignature.cle) }}<br>
              {{ form_widget(formWithElectroSignature.cle) }}

  </div>
  <div class="form-control">
   {{ form_label(formWithElectroSignature.document) }}<br>
              {{ form_widget(formWithElectroSignature.document) }}
  </div>
                <div class="form-control">

                    <div class="col-md-8 col-md-offset-2">
                        <br>
                        <?php echo isset($msg)?$msg:''; ?>
                        <h2>Signature Electronique !</h2>
                        <hr>
                        <div id="canvasDiv"></div>
                        <br>
                        <button type="button" class="btn btn-danger" id="reset-btn">Clear</button>
                        <button type="button" class="btn btn-success" id="btn-save">Save</button>
                    </div>
                    <form id="signatureform" action="" style="display:none" method="post">
                        <input type="hidden" id="signature" name="signature">
                        <input type="hidden" name="signaturesubmit" value="1">
                    </form>
                </div>
            </div>
            <div class="row">

  {{ form_end(formWithElectroSignature) }}

{% endblock %}

{% block body_javascript %}

<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<script src="/signatures/Signature.js"></script>

{% endblock %}

In the current state, i can see the drawning in the console. But it's not saved on the server. What i am missing, and am i in the right direction to do it ?

Cephalopodius
  • 117
  • 1
  • 10

1 Answers1

0

Canvas.toDataUrl return a base64 encoded string, if you want to use/save it as a file you first have to convert base64 string to a blob. Then this blob can be send with xml or Ajax request to you backend treatment.

You can find the process with sample in this answer to a similar question : https://stackoverflow.com/a/50538148/15282066

Camille
  • 847
  • 1
  • 7
  • 19