web-dev-qa-db-fra.com

Exporter les Highcharts vers PDF (utilisation de javascript et serveur local - pas de connexion internet)

J'utilise Highcharts dans mon application (sans connexion Internet)

J'ai plusieurs graphiques sur une page HTML et je souhaite générer un rapport PDF contenant tous les graphiques de cette page.

Comment puis-je faire cela sans envoyer les données à un serveur sur Internet?

Je serai reconnaissant pour toute aide ou tout exemple que vous pouvez fournir .. Merci d'avance :)

13
Leon

Oui, cela est possible, mais implique quelques bibliothèques différentes pour fonctionner. La première bibliothèque est jsPDF , qui permet la création de PDF dans le navigateur. Le second est canvg qui permet le rendu et l’analyse des fichiers SVG, ce qui est vraiment bien, mais peut rendre un svg sur un élément canvas. Enfin, le module d’exportation Highcharts nous permettra d’envoyer le fichier svg au lecteur pour le transformer en une URL de données pouvant ensuite être transmise à jsPDF en tant que fichier PDF.

Voici un exemple http://fiddle.jshell.net/leighking2/dct9tfvn/ que vous pouvez également voir dans les fichiers source que vous devrez inclure dans votre projet.

Donc, démarrer Highcharts fournit un exemple d'utilisation de canvg avec son export pour enregistrer un graphique au format png. parce que vous voulez toutes les images dans un pdf cela a été légèrement modifié pour que nous puissions simplement renvoyer l'URL des données

// create canvas function from highcharts example http://jsfiddle.net/highcharts/PDnmQ/
(function (H) {
    H.Chart.prototype.createCanvas = function (divId) {
        var svg = this.getSVG(),
            width = parseInt(svg.match(/width="([0-9]+)"/)[1]),
            height = parseInt(svg.match(/height="([0-9]+)"/)[1]),
            canvas = document.createElement('canvas');

        canvas.setAttribute('width', width);
        canvas.setAttribute('height', height);

        if (canvas.getContext && canvas.getContext('2d')) {

            canvg(canvas, svg);

            return canvas.toDataURL("image/jpeg");

        } 
        else {
            alert("Your browser doesn't support this feature, please use a modern browser");
            return false;
        }

    }
}(Highcharts));

Ensuite, pour l'exemple, j'ai configuré l'exportation sur un clic de bouton. Cela recherchera tous les éléments d'une classe donnée (donc choisissez-en un à ajouter à tous vos éléments de graphique), puis appelez leur fonction highcharts.createCanvas.

$('#export_all').click(function () {
    var doc = new jsPDF();

    // chart height defined here so each chart can be palced
    // in a different position
    var chartHeight = 80;

    // All units are in the set measurement for the document
    // This can be changed to "pt" (points), "mm" (Default), "cm", "in"
    doc.setFontSize(40);
    doc.text(35, 25, "My Exported Charts");

    //loop through each chart
    $('.myChart').each(function (index) {
        var imageData = $(this).highcharts().createCanvas();

        // add image to doc, if you have lots of charts,
        // you will need to check if you have gone bigger 
        // than a page and do doc.addPage() before adding 
        // another image.

        /**
        * addImage(imagedata, type, x, y, width, height)
        */
        doc.addImage(imageData, 'JPEG', 45, (index * chartHeight) + 40, 120, chartHeight);
    });


    //save with name
    doc.save('demo.pdf');
});

il est important de noter ici que si vous avez beaucoup de graphiques, vous devrez les placer sur une nouvelle page. La documentation de jsPDF semble vraiment dépassée (ils ont une bonne page de démos bien que peu expliquant toutes les options possibles), il existe une fonction addPage () et vous pouvez alors jouer avec les largeurs et les hauteurs jusqu'à ce que vous trouviez quelque chose qui travaux.

la dernière partie consiste simplement à configurer les graphiques avec une option supplémentaire pour ne pas afficher le bouton d'exportation sur chaque graphique qui s'afficherait normalement.

//charts
$('#chart1').highcharts({
    navigation: {
            buttonOptions: {
                enabled: false
            }
        },

//this is just normal highcharts setup form here for two graphs see fiddle for full details

Le résultat n’est pas si mauvais, je suis impressionné par la qualité des graphiques, car je ne l’attendais pas trop. Quelques jeux de positions et de tailles de fichiers PDF pourraient être vraiment beaux.

Voici une capture d'écran illustrant les demandes réseau effectuées avant et après l'exportation. Aucune exportation n'a lieu lorsque l'exportation est effectuée http://i.imgur.com/ppML6Gk.jpg

voici un exemple de ce à quoi ressemble le pdf http://i.imgur.com/6fQxLZf.png (semble meilleur quand on le voit comme un pdf réel)

exemple rapide à essayer sur local https://github.com/leighquince/HighChartLocalExport

30
Quince

Voici un exemple utilisant la bibliothèque pdfmake :

html:

<div id="chart_exchange" style="width: 450px; height: 400px; margin: 0 auto"></div>
<button id="export">export</button>
<canvas id="chart_exchange_canvas" width="450" height="400" style="display: none;"></canvas>

javascript:

function drawInlineSVG(svgElement, canvas_id, callback) {
  var can = document.getElementById(canvas_id);
  var ctx = can.getContext('2d');

  var img = new Image();
  img.setAttribute('src', 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgElement))));
  img.onload = function() {
    ctx.drawImage(img, 0, 0);
    callback(can.toDataURL("image/png"));
  }
}

code de travail complet: https://jsfiddle.net/dimitrisscript/f6sbdsps/

1

Vous devez configurer votre propre serveur d’exportation, localement comme dans le article

1
Sebastian Bochan

Cette question est un peu ancienne, mais c’était quelque chose sur laquelle je travaillais moi-même récemment et qui me posait quelques problèmes.

J'ai utilisé la bibliothèque jsPDF: https://github.com/MrRio/jsPDF

Les problèmes rencontrés dans jsPDF ne prenaient pas en charge l’image SVG exportée par le diagramme supérieur + les images étant floues et de qualité médiocre.

Vous trouverez ci-dessous la solution que j’ai utilisée pour rassembler deux graphiques dans un document pdf: 

function createPDF() {
var doc = new jsPDF('p', 'pt', 'a4'); //Create pdf

if ($('#chart1').length > 0) {
    var chartSVG = $('#chart1').highcharts().getSVG();
    var chartImg = new Image();

    chartImg.onload = function () {

        var w = 762;
        var h = 600;

        var chartCanvas = document.createElement('canvas');
        chartCanvas.width = w * 2;
        chartCanvas.height = h * 2;
        chartCanvas.style.width = w + 'px';
        chartCanvas.style.height = h + 'px';
        var context = chartCanvas.getContext('2d');
        chartCanvas.webkitImageSmoothingEnabled = true;
        chartCanvas.mozImageSmoothingEnabled = true;
        chartCanvas.imageSmoothingEnabled = true;
        chartCanvas.imageSmoothingQuality = "high";
        context.scale(2, 2);
        chartCanvas.getContext('2d').drawImage(chartImg, 0, 0, 762, 600);

        var chartImgData = chartCanvas.toDataURL("image/png");
        doc.addImage(chartImgData, 'png', 40, 260, 250, 275);

        if ($('#chart2').length > 0) {
            var chart2SVG = $('#chart2').highcharts().getSVG(),
                chart2Img = new Image();

            chart2Img.onload = function () {

                var chart2Canvas = document.createElement('canvas');
                chart2Canvas.width = w * 2;
                chart2Canvas.height = h * 2;
                chart2Canvas.style.width = w + 'px';
                chart2Canvas.style.height = h + 'px';
                var context = chart2Canvas.getContext('2d');
                chart2Canvas.webkitImageSmoothingEnabled = true;
                chart2Canvas.mozImageSmoothingEnabled = true;
                chart2Canvas.imageSmoothingEnabled = true;
                chart2Canvas.imageSmoothingQuality = "high";
                context.scale(2, 2);
                chart2Canvas.getContext('2d').drawImage(chart2Img, 0, 0, 762, 600);

                var chart2ImgData = chart2Canvas.toDataURL("image/png");
                doc.addImage(chart2ImgData, 'PNG', 300, 260, 250, 275);

                doc.save('ChartReport.pdf');
            }

            chart2Img.src = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(chart2SVG)));
        }
    }
    chartImg.src = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(chartSVG)));
}
}

scripts à inclure:

 <script src="http://code.highcharts.com/highcharts.js"></script>
 <script src="http://code.highcharts.com/modules/exporting.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js"></script>
0
Ryan Gavin

Peut-être que ce lien peut vous aider.

http://bit.ly/1IYJIyF

Essayez de vous reporter aux propriétés d'exportation (fallbackToExportServer: false) et au fichier nécessaire à inclure (offline-export.js).

Alors que pour l'exportation tout à la fois, actuellement, j'essaie encore moi-même. Mettra à jour ici s'il y en a.

0
William Kheng