Экспорт Highcharts в PDF (с использованием javascript и локального сервера - без подключения к Интернету)

Я использую Highcharts в своем приложении (без подключения к Интернету)

У меня есть несколько диаграмм на странице html, и я хочу создать отчет в формате PDF, содержащий все диаграммы на этой странице.

Как я могу сделать это без отправки данных на любой сервер в Интернете?

Я буду благодарен за любую помощь или любой пример, который вы можете предоставить. Заранее спасибо:)

Ответ 1

Да, это возможно, но для работы требуется несколько разных библиотек. Первая библиотека jsPDF, которая позволяет создавать PDF файлы в браузере. Второй - canvg, который позволяет визуализировать и анализировать SVG, бит, который действительно крут, хотя он может отображать svg на элемент canvas. Наконец, модуль экспорта Highcharts, который позволит нам отправить svg в canvg, чтобы превратиться в URL-адрес данных, который затем можно передать jsPDF, чтобы он превратился в ваш pdf.

Вот пример http://fiddle.jshell.net/leighking2/dct9tfvn/, вы также можете увидеть там исходные файлы, которые вам нужно будет включить в свой проект.

Итак, чтобы запустить highcharts, вы можете использовать canvg с его экспортом, чтобы сохранить диаграмму в виде png. потому что вы хотите, чтобы все iamges в формате pdf были слегка изменены для нашей цели, чтобы просто вернуть URL-адрес данных

// 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));

Тогда для примера я установил экспорт нажатием кнопки. Это будет искать все элементы определенного класса (поэтому выберите один для добавления ко всем вашим элементам диаграммы), а затем вызовите их функцию 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');
});

Важно отметить, что если у вас много диаграмм, вам нужно будет обрабатывать их размещение на новой странице. Документация для jsPDF выглядит действительно устаревшей (у них действительно хорошая демонстрационная страница, хотя просто не так много объяснять все возможные варианты), есть функция addPage(), и тогда вы можете просто играть с шириной и высотами, пока не найдете что-то, что работы.

Последняя часть - просто настроить графики с дополнительной опцией, чтобы не отображать кнопку экспорта на каждом графике, который обычно отображается.

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

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

Результат не так уж плох, я впечатлен качеством графиков, поскольку я не ожидал от этого многого, и некоторые игры в позициях и размерах в формате pdf выглядели бы очень хорошо.

Вот скриншот, показывающий сетевые запросы, сделанные до и после экспорта, когда экспорт не выполняется, запросы не выполняются http://i.imgur.com/ppML6Gk.jpg

вот пример того, что PDF выглядит как http://i.imgur.com/6fQxLZf.png (выглядит лучше, когда просмотр как фактический pdf)

быстрый пример для проверки на локальном https://github.com/leighquince/HighChartLocalExport

Ответ 2

Вам нужно настроить собственный сервер экспорта, как в статье

Ответ 3

Возможно, эта ссылка может помочь вам.

http://bit.ly/1IYJIyF

Попробуйте обратиться к свойствам экспорта (fallbackToExportServer: false) и к необходимому файлу, который необходимо включить (offline-exporting.js).

В то время как для экспорта все сразу часть, в настоящее время я сам тоже все еще пытаюсь. Будет обновляться здесь, если таковые имеются.

Ответ 4

Этот вопрос немного стар, но я недавно работал над собой и имел некоторые проблемы с ним.

Я использовал библиотеку jsPDF: https://github.com/MrRio/jsPDF

Проблемы, с которыми я столкнулся, связаны с jsPDF, не поддерживающим изображение SVG, экспортируемое с высокой графикой + изображения размытыми и низкими качествами.

Ниже приведено решение, которое я использовал для получения двух диаграмм в одном документе 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)));
}
}

для включения:

 <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>

Ответ 5

Вот пример использования библиотеки 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"));
  }
}

полный рабочий код: https://jsfiddle.net/dimitrisscript/f6sbdsps/