2014-09-02 7 views
11

Używam Highcharts w mojej aplikacji (bez połączenia internetowego)Export Highcharts do formatu PDF (za pomocą JavaScript i serwer lokalny - bez połączenia internetowego)

Mam kilka wykresów na stronie html i chcę, aby wygenerować Raport PDF zawierający wszystkie wykresy z tej strony.

Jak mogę to zrobić, nie wysyłając danych do żadnego serwera w Internecie?

Będę wdzięczny za każdą pomoc lub dowolny przykład, który możesz dostarczyć. Z góry dziękuję :)

Odpowiedz

26

Tak, jest to możliwe, ale wymaga kilku bibliotek do pracy. Pierwsza biblioteka to jsPDF, która umożliwia tworzenie plików PDF w przeglądarce. Druga to canvg, która pozwala na renderowanie i parsowanie SVG, bit, który jest naprawdę fajny, choć może renderować element SVV na element canvas. Wreszcie jest Highcharts export module, który pozwoli nam wysłać svg do canvg, aby zmienić adres URL danych, które następnie można przekazać jsPDF, aby przekształcić go w plik pdf.

Oto przykład http://fiddle.jshell.net/leighking2/dct9tfvn/ można również zobaczyć tam pliki źródłowe, które należy uwzględnić w projekcie.

Rozpoczęcie highcharts daje przykład użycia canvg z jego eksportem do zapisania wykresu jako png. ponieważ chcesz wszystkie iamges w pdf ten został nieznacznie zmienione dla naszego celu, aby tylko wrócić url danych

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

Następnie na przykład mam skonfigurować eksport na kliknięcia przycisku. Spowoduje to wyszukanie wszystkich elementów danej klasy (wybierz więc jeden element do dodania do wszystkich elementów wykresu), a następnie wywołaj ich funkcję 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'); 
}); 

Ważne jest, aby pamiętać, że jeśli masz dużo wykresów, musisz zająć się umieszczaniem ich na nowej stronie. Dokumentacja dla jsPDF wygląda naprawdę nieaktualnie (mają dobrą stronę demonstracyjną, ale nie wiele, aby wyjaśnić wszystkie możliwe opcje), istnieje funkcja addPage(), a następnie możesz po prostu grać z szerokością i wysokością, aż znajdziesz coś, Prace.

ostatnią częścią jest ustawienie wykresów z dodatkową opcją, aby nie wyświetlać przycisku eksportu na każdym wykresie, który normalnie byłby wyświetlany.

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

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

Wynik nie jest tak źle, że jestem pod wrażeniem jakości wykresów, bo nie spodziewałem się wiele od tego, z jakiegoś grania stanowisk i rozmiarach pdf mogłaby wyglądać naprawdę dobrze.

Oto zrzut ekranu przedstawiający żądania sieciowe wykonane przed i po eksporcie, gdy eksport jest wykonane żadne wnioski są http://i.imgur.com/ppML6Gk.jpg

Oto przykład tego, co pdf wygląda http://i.imgur.com/6fQxLZf.png (wygląda lepiej, gdy widok jako rzeczywistego pdf)

szybkie przykład być sądzony na lokalnym https://github.com/leighquince/HighChartLocalExport

+0

Dziękuję za pomoc, ale w tym roztworze dane są wysyłane do Highcharts Export Server. I nie chcę, żeby tak się stało, jak powiedziałem w pytaniu :)) – Leon

+0

Nie Użyłem tylko modułu eksportu, aby uzyskać dane SVG, oglądałem kartę sieci i żadne dane nie zostały wysłane. – Quince

+0

Konwersja wszystko dzieje się w przeglądarka, dlatego też wyłączyłem przycisk eksportu na każdym wykresie – Quince

1

Musisz skonfigurować własny serwer wywozu, lokalnie jak w article

0

Może ten link może ci pomóc.

http://bit.ly/1IYJIyF

Przymierz odnoszą się do właściwości eksportujących (fallbackToExportServer: false) oraz niezbędnego pliku, który trzeba podać (w trybie offline exporting.js).

Podczas gdy do eksportu wszystkie części, obecnie ja również próbuję. Zaktualizuje się tutaj, jeśli jest.

0

To pytanie jest trochę stare, ale było coś, nad czym ostatnio pracowałem i miałem z tym problem.

użyłem biblioteki jsPDF: https://github.com/MrRio/jsPDF

Problemy wpadłem zaangażowanych jsPDF nie wspiera obraz SVG eksportowany przez wysoką wykresie + obrazów będącego rozmyte i niskiej jakości.

Poniżej jest rozwiązaniem kiedyś dostać dwa wykresy w jednym dokumencie 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))); 
} 
} 

skrypty obejmują:

<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

Oto przykład przy użyciu biblioteki 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")); 
    } 
} 

pełny kod roboczych: https://jsfiddle.net/dimitrisscript/f6sbdsps/

Powiązane problemy