Search code examples
javascriptjquerycordovahtml-framework-7canvasjs

Cordova Framework7 using CanvasJS to export Image


I have and application running Framework7 build with Cordova and I'm using CanvasJS to generate different Charts. However, upon using CanvasJS while is build under Cordova and enabling the export option for the user to download the Chart as PNG/JPG, when the button is clicked nothing happens, although everything works fine through the browser and the image is downloaded fine.

What can be the issue?

Thanks!

I suspect I may need to extract the CanvasJS image manually

var canvas = $("#chartContainer .canvasjs-chart-canvas").get(0);
var dataURL = canvas.toDataURL('image/png');

and use something like cordova-plugin-file-transfer to send that image dirrectly to the user phone, or there is a better way integrated into CanvasJS ?


Solution

  • I found a solution a while ago and decided to come back to my question and post it. Hopefully it will help someone with the same problem in the future.

    So my solution is as follows:

    // ... your Canvas logic ... use the code after chart.render(); //
    // I've decided to remove the original Canvas drop-down button and replace it with a simple one
    $(".canvasjs-chart-toolbar").html('<button class="button button-fill button-small" id="download_image">Download Image</button>');
    // Hooking the newly replaced button with OnClick function
    $('#download_image').click(function () {
        // Just adding a small alert showing the user the image is being downloaded
        dialog.alert('Please wait... <div class="preloader color-blue"></div>', "Downloading Image");
        // Collecting the image from the Canvas container
        var canvas = $("#chartContainer .canvasjs-chart-canvas").get(0);
        var dataURL = canvas.toDataURL('image/png');
        var f_name = "dwn_chart.png"; // You can use any name you want
    
        var downloadFile = function () {
            var download = function(fileEntry, uri, readBinaryData) {
                var fileTransfer = new FileTransfer();
                var fileURL = fileEntry.toURL();
                fileTransfer.download(
                    uri, fileURL,
                    function (entry) {
                        var onSaveImageSuccess = function() { dialog.close(); dialog.alert("File: " + f_name, "Download Success"); };                                    
                        var onSaveImageError = function(error) { dialog.close(); dialog.alert(error, "Download Error"); };
                        // Using Cordova ImageSaver to appropriately save the image to the user gallery
                        window.cordova.plugins.imagesaver.saveImageToGallery(entry.toURL(), onSaveImageSuccess, onSaveImageError);
                    },
                    function (error) {
                        dialog.close(); var error = String(error.source);
                        dialog.alert('<p style="color: #800000;">Download Error: <b>' + error + '</b></p>' +
                            '<p>Please refresh the Chart and try again, if the problem persists, contact support. Thank you.</p>');
                    }, null, {}
                );
            };
    
            var onErrorLoadFs = function() { dialog.close(); dialog.alert("Error loading file.", "Download Error"); };
            var onErrorCreateFile = function() { dialog.close(); dialog.alert("Error creating file.", "Download Error"); };
            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
                // Make sure you add the domain name to the Content-Security-Policy <meta> element.
                var url = rIP + "PPM/data/" + f_name; // Example: https://yourweb.com/path_to_file/file_name.png (f_name)
                // Parameters passed to getFile create a new file or return the file if it already exists.
                fs.root.getFile(f_name, { create: true, exclusive: false }, function (fileEntry) {
                    download(fileEntry, url, true);
                }, onErrorCreateFile);
            }, onErrorLoadFs);
        };
    
        // Sending the image URI to my PHP file through AJAX located on the server so it can be saved
        $.ajax({
            cache: false,
            type: "POST",
            url: rIP + "PPM/save_chart.php", // Here you should use the address of your PHP file handling the save https://yourweb.com/your_save_php_file.php
            data: { 'URI': dataURL, 'Name': f_name }, // Sending the URI and the desired Name
            success: function () {
                downloadFile(); // When is done saving it the downloadFile() function is called
            }
        });
    });
    

    My PHP Save file:

    <?php
        $Data = $_POST['URI'];
        $Name = $_POST['Name'];
    
        function SaveChartIMG($Data, $Name) {
            $imgData = str_replace(' ','+', $Data);
            $imgData =  substr($imgData,strpos($imgData,",")+1);
            $imgData = base64_decode($imgData);
            // Path where the image is going to be saved
            $filePath = $_SERVER['DOCUMENT_ROOT']. '/PPM/data/'.$Name;
            // Write $imgData into the image file
            $file = fopen($filePath, 'w');
            fwrite($file, $imgData);
            fclose($file);
        }
    
        SaveChartIMG($Data, $Name);
    ?>
    

    I know my code may not be the best efficient way, so feel free to edit it and tweak it as you see fit. I hope it will help someone.

    Cordova Plugins used:

    <plugin name="cordova-plugin-file" spec="4.3.3"/>
    <plugin name="cordova-plugin-file-transfer" spec="1.6.3"/>
    <plugin name="cordova-plugin-save-image"/>