Search code examples
phpjquerylaravelhtml2canvas

convert div data to image using html2canvas and php


I want to convert my div data to image and stored it in directory and db using Ajax request on button click. The code executes well and stores data both in directory and db but the problem is that when I click the button for first time it does not do anything but when I click button for the second time and so on it stores the the image correctly in both places. I don't know where i am going wrong, any suggestion would be highly appreciated. Thanks!

My View code:

<div id='calendar'>-- Data I want to convert to image --</div>

<form method="post" enctype="multipart/form-data" id="myForm">
    {{csrf_field()}}
    <input type="hidden" name="img_val" id="img_val" value="" />
    <input type="submit" id="take_shot" value="Take Screenshot"/>
</form>

My Jquery Code:

<!-- Canvas Jquery Code for saving screenshot -->
<meta name="csrf-token" content="{{ csrf_token() }}" /> 
<meta name="screenShot" content="{{url('htmlcanvas')}}">

<script>
$.ajaxSetup({
    headers: {

        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
    }
});
</script>

<script type="text/javascript">
$(document).ready(function(){
 var dataurl = "";
 $('#take_shot').click(function(){
    $('#calendar').html2canvas({
        onrendered: function (canvas) {
            //Set hidden field's value to image data (base-64 string)
            dataurl = $('#img_val').val(canvas.toDataURL("image/png"));
        }
    });
    var form_data = new FormData($("#myForm")[0]);

        $.ajax({
            type:'POST',
            url: $('meta[name="screenShot"]').attr('content'),
            data : form_data,
            cache: false,
            processData: false,
            contentType: false,

            success:function(data){
                alert(data);
            }
        }); 

    return false;
 });
});
</script>

My Controller code:

    public function storeImageHtmlCanvas(Request $request)
        {
            if($request->ajax()) {
                if($request->img_val != null)
                {
                   $dbImage = new Admin_Image;
                   $data_uri = $request->img_val;
                   $encoded_image = explode(",", $data_uri)[1];
                   $decoded_image = base64_decode($encoded_image);
                   $path = storage_path() . '/screenshots/';
                   $file_name = time();
                   file_put_contents($path.$file_name.".png", $decoded_image);
$dbImage->admin_image =  $file_name.".png" ;
$dbImage->save();
                   $output = "success";   
                }
                return response()->json($output);
            }
        }

Solution

  • html2canvas is asynchronous (~= it executes in background while the script continues to run) so when the first Ajax request runs, dataurl is undefined.

    You need to trigger the AJAX request inside the onrendered function, like so

        $('#take_shot').click(function(){
            $('#calendar').html2canvas({
                onrendered: function (canvas) {
    
    
                //Set hidden field's value to image data (base-64 string)
                dataurl = $('#img_val').val(canvas.toDataURL("image/png"));
    
                // dataurl is defined, you can trigger the ajax request
                var form_data = new FormData($("#myForm")[0]);
    
                $.ajax({
                    type:'POST',
                    url: $('meta[name="screenShot"]').attr('content'),
                    data : form_data,
                    cache: false,
                    processData: false,
                    contentType: false,
    
                    success:function(data){
                        alert(data);
                    }
                }); 
    
                }
            });
    
            return false;
         });
        });