Wkhtmltopdf не отображает график Chart.JS 2.5.0

Использование:
WKpdftohml версия 0.12.3.2
PHPwkhtmltopdf версия 2.2.0
Chart.JS версия 2.5.0

Я пытаюсь напечатать линейный график с использованием вышеуказанных библиотек. Я могу воспроизвести PDF с помощью команды оболочки: wkhtmltopdf --javascript-delay 5000 " http://netdna.webdesignerdepot.com/uploads7/easily-create-stunning-animated-charts-with-chart-js/chartjs-demo.html" test2.pdf
Так что с WKhtmltopdf проблем нет.

Проблема в том, когда я делаю это в своем приложении, используя библиотеку PHPwkhtmltopdf. Я получаю пустую страницу.
Из моих исследований вот что я пробовал:

  • добавленной 'javascript-delay' => 500 к Chart.JS опциям;
  • добавленной animation:{onComplete: function () {window.JSREPORT_READY_TO_START =true} к Chart.JS опциям;
  • добавленной <div style="width:800px;height:200;font-size:10px;"> html тегу родительского div холста
  • добавленной ctx.canvas.width = 800;ctx.canvas.height = 200; для javascript инициализации диаграммы.

Ну, ничего не сработало. Я люблю Chart.JS и WKhtmltopdf, но если я не смогу распечатать, мне придется отказаться от одного из них. Есть ли решение?

Это мой PHP-код для PHPwkhtmltopdf:

public function imprimir ($request, $response)
{
    // include_once 'config/constants.php';
    // include_once 'resources/auxiliar/helpers.php';

    $folha = $_POST['printit'];
    $variaveis = explode(',', $folha);

    $nomeFicheiro = $variaveis[0];

    $printName = substr($nomeFicheiro, 5);

    if (isset($variaveis[2])) {

        $_SESSION['mesNumero'] = $variaveis[2];
        $_SESSION['mes'] = $variaveis[1];

    } else {

        $mesNumero = 0;
        $mes = '';

    }

    ob_start();
    if ($nomeFicheiro == 'printPpiam') {
        require ('C:/xampp/htdocs/.../'.$nomeFicheiro.'.php');
    } else {
        require ('C:/xampp/htdocs/.../'.$nomeFicheiro.'.php');
    }
    $content = ob_get_clean();

    // You can pass a filename, a HTML string, an URL or an options array to the constructor
    $pdf = new Pdf($content);

    // On some systems you may have to set the path to the wkhtmltopdf executable
    $pdf->binary = 'C:/Program Files/wkhtmltopdf/bin/wkhtmltopdf';

    $pdf -> setOptions(['orientation' => 'Landscape',
                        'javascript-delay' => 500,
                        // 'enable-javascript' => true,
                        // 'no-stop-slow-scripts' => true]
                    ]);

    if (!$pdf->send($printName.'.pdf')) {
        throw new Exception('Could not create PDF: '.$pdf->getError());
    }

    $pdf->send($printName.'.pdf');

}  

# Обновление 1
Сделал php файл с выводом страницы. Запустите его в браузере и график отображается. Когда я делаю это в консоли, он рендерит все, кроме графика!
Как это может быть, wkhtmltopdf отображает графику на этой странице: http://netdna.webdesignerdepot.com/uploads7/easily-create-stunning-animated-charts-with-chart-js/chartjs-demo.html но не мой?!

9 ответов

Вот код, который работает с wkhtmltopdf версия 0.12.5:

chart.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<style>
    .reportGraph {width:900px}
</style>
</head>
<body>

<div class="reportGraph"><canvas id="canvas"></canvas></div>

<script type="text/javascript">
// wkhtmltopdf 0.12.5 crash fix.
// https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192
'use strict';
(function(setLineDash) {
    CanvasRenderingContext2D.prototype.setLineDash = function() {
        if(!arguments[0].length){
            arguments[0] = [1,0];
        }
        // Now, call the original method
        return setLineDash.apply(this, arguments);
    };
})(CanvasRenderingContext2D.prototype.setLineDash);
Function.prototype.bind = Function.prototype.bind || function (thisp) {
    var fn = this;
    return function () {
        return fn.apply(thisp, arguments);
    };
};

function drawGraphs() {
    new Chart(
        document.getElementById("canvas"), {
            "responsive": false,
            "type":"line",
            "data":{"labels":["January","February","March","April","May","June","July"],"datasets":[{"label":"My First Dataset","data":[65,59,80,81,56,55,40],"fill":false,"borderColor":"rgb(75, 192, 192)","lineTension":0.1}]},
            "options":{}
        }
    );
}
window.onload = function() {
    drawGraphs();
};
</script>
</body>
</html>

Пробег:

$ wkhtmltopdf chart.html chart.pdf:

Loading pages (1/6)
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done

Нашел ответ. После того, как я создал отдельный файл вне фреймворка, я снова провел несколько тестов. Он отобразил график в браузере, поэтому я попытался использовать командный инструмент WKhtmltopdf, и он не сработал, как это было с другими примерами (см. Обновление № 1). Так что с моей страницей php что-то не так.
Запустил те же тесты, что и в рамках, и получил ответ на мою проблему. Введя размеры ширины родительского тега div в тег canvas, он сделал визуализацию графика на странице.

<div style="width:800px;height:200;">
    <canvas id="myChart" style="width:800px;height:200;"></canvas>
</div>

Предложение было найдено на этом сайте: Github, так что спасибо laguiz.

Попробуйте добавить это,

<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.0.0/polyfill.min.js"></script>

Это сработало для меня.

Источник: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2952

Решил это путем понижения wkhtmltopdf: 0.12.4 > 0.12.2.1

Версия chart.js, похоже, не имела никакого влияния. Я использовал 2.7.0.

Фиксированная ширина и высота, кажется, также необходимы.

Я имел дело с той же проблемой, используя rotativa для экспорта моей страницы ASP.NET MVC с Chart.JS в PDF, но безуспешно.

Через пару дней я наконец нашел супер-простое решение для достижения своей цели. Я просто использовал метод.toBase64Image() Chart.JS для кодирования диаграммы в строковую переменную base64 в Javascript. Затем я сохранил эту строку в модели, а затем на странице PDF html использованный тег, где я поместил строку в кодировке base64 в свойство scr, и результат отличный:-)

javascript:

//save Chart as Image
var url_base64 = document.getElementById('myChart').toDataURL('image/png');

//set the string as a value of a hidden element
document.getElementById('base64graph').value = url_base64;

Просмотр PDF:

<img style='display:block; width:900px;height:400px;position:relative;margin:auto;text-align:center;' id='base64image'
         src='@Model.base64graph' />

Я пытаюсь улучшить ответ temuri , это здорово, но немного раздуто. Я столкнулся с проблемами OP (даже с той же версией WKpdftohml), и это помогло мне:

      <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>

<div style="width: 400px;"><canvas id="canvas"></canvas></div>

<script type="application/javascript">
    // wkhtmltopdf 0.12.5 crash fix.
    // https://github.com/wkhtmltopdf/wkhtmltopdf/issues/3242#issuecomment-518099192

    Function.prototype.bind = Function.prototype.bind || function (thisp) {
        const fn = this;
        return function () {
            return fn.apply(thisp, arguments);
        };
    };

    new Chart(
        document.getElementById("canvas"), {
            "responsive": false,
            "type":"line",
            "data":{"labels":["January","February","March","April","May","June","July"],"datasets":[{"label":"My First Dataset","data":[65,59,80,81,56,55,40],"fill":false,"borderColor":"rgb(75, 192, 192)","lineTension":0.1}]},
            "options":{}
        }
    );
</script>

Мне еще предстоит выяснить, как получить библиотеку диаграмм с помощью обычных инструментов, таких как npm, вместо того, чтобы получать ее через ajax, как здесь, в первой строке. Обратите внимание, что это может повлиять на разрешение диаграммы.

Я тоже боролся с этим, и ты сам не ответил на мой вопрос. Я использую Symfony 3.3 и Chart.js 2, и что бы я ни делал, не работало должным образом. Таким образом, я решил это по-другому (возможно, не чисто), и я хотел опубликовать это здесь для вдохновения другим.

Мне нужно было экспортировать страницу, которую я представлял пользователю в браузере. В браузере я использовал Javascript, чтобы получить изображение из визуализированного графика с

animation: {
                onComplete: function(animation) {
                    console.log('done');
                    var url=document.getElementById("barChartByCountryWeight{{ part }}{{ subsetKey }}").toDataURL();
                    $.ajax({
                        url: 'saveChartImages',
                        type: 'POST',
                        data: { 'barChartByCountryWeight{{ part }}{{ subsetKey }}': url },
                        success: function(result) {
                            console.log(result);
                            console.log('the request was successfully sent to the server');
                        },
                        error: function (request, error) {
                            console.log(arguments[0]['responseText']);
                            console.log(" Can't do because: " + error);
                        }
                    });

                }
            }

И на стороне сервера я поместил его в сессию и в контроллер для экспорта в PDF, я взял изображение из сессии и поместил изображение в HTML, который преобразуется в PDF.

Надеюсь, это поможет.

Я реализовал рабочий код для этой проблемы. Вы можете посмотреть рабочий код здесь.

ПРИМЕЧАНИЕ. Для создания PDF необходимо отключить Chart JS анимация или добавить опцию javascript-delay=>1000 к wkhtmltopdf параметры.

Да, я решил эту проблему, попробуйте использовать Chartjs 1, а не новую диаграмму js, потому что laravel snappy использует wkhtmltopdf, который не поддерживает анимацию css, а новый chartjs использует анимацию css https://github.com/chartjs/Chart.js/issues/4767 покажите это, и решение, которое я нашел, состоит в том, чтобы использовать диаграмму Google, которая использует SVG, чтобы вы могли получить диаграмму высокого разрешения

Другие вопросы по тегам