首页 > 解决方案 > KnpLabs/snappy bundle (wkhtmltopdf) 不呈现 Chart.js 图表

问题描述

我试图PDF用库生成的图表生成,Chart.js但 javascript 根本不呈现。

你看到我错过了什么吗?

   # config/packages/knp_snappy.yaml
    knp_snappy:
        pdf:
            enabled:    true
            binary:     '%env(WKHTMLTOPDF_PATH)%'
            options:
              debug-javascript: true
              enable-javascript: true
              javascript-delay: 200
              no-stop-slow-scripts: true

        image:
            enabled:    true
            binary:     '%env(WKHTMLTOIMAGE_PATH)%'
            options:    []

PHP Symfony 部分

    /**
     * Download pdf.
     *
     * @param string $slug
     * @param string $language
     *
     * @return Response
     *
     * @throws \Psr\Cache\CacheException
     * @throws \Psr\Cache\InvalidArgumentException
     */
    public function __invoke(string $slug, string $language): Response
    {
            $this->pdfFilesService->setPdfLanguage($language);
            $base64Images = $this->pdfFilesService->getBase64Images($slug);
            $profile      = $this->profileData->execute($slug, $language);
            $filename     = $profile['name'].'-report.pdf';
            $path         = $this->parameterBag->get('app.private_pdf_storage').'/'.$filename;

            $html = $this->templating->render('download_pdf.twig', \array_merge($base64Images, [
                'profile'     => $profile,
                'language'    => $language,
            ]));


            $this->pdf->generateFromHtml([$html], $path, [], true);

            return new Response(
                $path,
                200,
                [
                    'Content-Type'        => 'application/pdf',
                    'Content-Disposition' => 'inline; filename="'.$path.'"',
                ]
            );

    }

枝条

   <section>
       <div id="barMulti"></div>
   </section>
   <script type="text/javascript" src="{{ chartJs }}"></script>
   <script type="text/javascript">
      function getDataMulti(type) {
         return {
            // The type of chart we want to create
            type,

            // The data for our dataset
            data: {
               labels: [ ... ],
               datasets: [
                  {
                     backgroundColor: "#F4F7F9",
                     data: [3,7,4,5,5,2,6,8,9,7]
                  },
                  {
                     backgroundColor: "#66C4E0",
                     data: [3,7,4,5,5,2,6,8,9,7]
                  },
                  {
                     backgroundColor: "#009DCD",
                     data: [3,7,4,5,5,2,6,8,9,7]
                  },
               ]
            },

            // Configuration options go here
            options: {
               legend: {
                  display: false,
               },
               animation: {
                  duration: 0
               },
               scales: {
                  yAxes: [{
                     gridLines: {
                        color: "#454D57",
                     },
                     ticks: {
                        padding: 20,
                        fontStyle: 'bold',
                        fontColor: '#F4F7F9',
                        min: 0,
                        max: 100,
                     }
                  }],
                  xAxes: [
                     {
                        gridLines: {
                           color: "#454D57"
                        },
                        ticks: {
                           fontStyle: 'bold',
                           fontColor: '#F4F7F9',
                           padding: 20,
                           callback: function(label) {
                              if (/\s/.test(label)) {
                                 return label.split(" ");
                              }

                              return label;
                           }
                        }
                     }
                  ]
               }
            }
         }
      }

      // var barMulti = document.getElementById('barMulti');
      var barMulti = document.getElementById('barMulti');
      new Chart(barMulti, getDataMulti('bar'));
   </script>

标签: javascriptphpsymfonychartswkhtmltopdf

解决方案


wkhtmltopdf不是一个完美的库,但它是开源的并且可以免费 使用,所以我们需要心存感激,并尝试通过贡献来帮助它的使用或改进。

wkhtmltopdf GitHub 存储库

作为第一步,您需要测试您的 HTML/TWIG 模板以使用 Javascript。

<script>
  document.body.innerHTML = "Testing JavaScript PDF Rendering"
</script>

如果这不起作用,请检查您的wkhtmltopdf配置

  # config/packages/knp_snappy.yaml
    knp_snappy:
        pdf:
            enabled:    true
            binary:     '%env(WKHTMLTOPDF_PATH)%'
            options:
              debug-javascript: true
              enable-javascript: true
              javascript-delay: 1500
              no-stop-slow-scripts: true

在您确定 Javascript 可以工作之后wkhtmltopdf

最重要的事情。你需要canvasstyled div

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

并放入headcss放入样式类

   .reportGraph {
      width:850px
   }

或者可能通过内联 css 样式画布容器

然后在包含chart.js库后添加此脚本文件

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

然后添加另一个script标签,您将在其中呈现图表。

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

推荐阅读