【问题标题】:Google Charts not working with Wkhtmltopdf谷歌图表不适用于 Wkhtmltopdf
【发布时间】:2013-10-19 21:03:39
【问题描述】:

我正在尝试使用 Google Charts 在 PDF 中生成多个图表。对于 PDF,我将 CakePDF 与 Wkhtmltopdf 引擎一起使用。不过,我似乎在将 Google Chart 代码实际加载到 PDF 中时遇到了问题。这是我当前的 Javascript 代码。

<script type="text/javascript" src="https://www.google.com/jsapi">
</script>
<script type="text/javascript">
google.load('visualization', '1.0', {'packages':['corechart']});
//setTimeout(function() {google.load('visualization', '1.0', {'packages':['corechart']});}, 100);
google.setOnLoadCallback(drawChart);
function drawChart(doIt,taken, total, element) 
{
    if (typeof doIt === 'boolean')
    {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Type');
        data.addColumn('number', 'Courses');
        data.addRows([
          ['Taken', taken],
          ['Remaining', total - taken]
        ]);
        var options = {
                       'width':40,
                       'height':40};
        var chart = new google.visualization.PieChart(document.getElementById(element));
        chart.draw(data, options);
    }
 }
</script>

问题是,当我为可视化包执行 google.load 时,它会导致 Wkhtmltopdf 返回错误,指出引擎未返回任何数据。我在Why does google.load cause my page to go blank? 发现了一个我认为类似的问题,所以我尝试执行 setTimeout(function() {google.load('visualization', '1.0', {'packages':['corechart']});} , 100);这个解决方案的问题是,如果延迟太低,页面将返回没有错误,但它会完全空白;但是,如果我将延迟设置得太高,页面将不会加载包并且 Javascript 将在

处中断
var data = new google.visualization.DataTable();

当我调用函数时。此外,该海报说明了 document.write() 的问题,但如果我在将内容添加到页面之前或之后添加 document.write() 行,我没有问题。如果有人知道如何让 Google Charts 与 Wkhtmltopdf 一起工作并能帮助我,我将不胜感激。


好的,为了给 API 更多的加载时间,我将调用函数的位置移到了 PHP 的末尾。现在,它只设置一个需要在其中绘制图形的元素数组和适当的值,然后使用数组中的值调用函数。我不确定现在的问题是什么,因为它现在正在打破chart.draw(data, options);。它似乎正在获取正确的值和传递给它的元素。

这看起来真的很迂回,因为它是。无论出于何种原因,Wkhtmltopdf 都无法读取我放入 javascript 标签中的任何内容。我已经尽我所能让它阅读它,但它就是不会哈哈。 CakePDF 插件可以读取 Javascript,所以我的 JS 代码是默认的 PDF 布局。然后在 WkhtmltoPdf 呈现的实际视图中,我创建了一个元素和值的数组。然后我这样做(在许多不同的可能解决方案之后,这是我能够调用 JS 函数的唯一方法)

for ($i = 0; $i < sizeof($grade_array); $i++)
{
    $element = $grade_array[$i][2];
    echo '<script type="text/javascript">drawChart(true, '.$this->Js->value($grade_array[$i][0]).', '.$this->Js->value($grade_array[$i][1]).','.json_encode($element).');</script>';
}

它似乎传递了所有正确的数据。调用该函数后,我有打印参数的调试行,并且所有参数都正确打印。我还注意到,如果我在与 chart.draw() 相同的位置执行 document.write('test'),它将写入 'test' 而不会出现任何错误。出于某种原因,如果我执行 chart.draw(),它只是说 Wkhtmltopdf 没有返回任何数据。

【问题讨论】:

  • 鉴于您发布的代码,if (typeof doIt === 'boolean') 无法返回 true,因为来自 google.load 调用的回调没有参数(doIt 将始终为空)。如果var data = new google.visualization.DataTable(); 行出现错误,您必须在其他地方调用drawChart 函数。这是您的全部代码还是还有更多内容?
  • 对此我很抱歉。我稍后调用函数本身,并传递必要的参数。我知道它在那一行中断了,因为我实际上有一个调试行来在每行之后打印一条消息,所以我知道它在哪里中断;我只是删除了那些以使代码更易于阅读。我确信该函数是使用正确的参数调用的。
  • 如果在 API 完成加载之前调用函数,您可能会收到错误 - 回调的目的是确保首先加载所有内容。尝试安排您的代码,使drawChart 调用的触发器发生在来自谷歌加载程序的回调内部(不必是drawChart 函数本身)。
  • 我不确定该怎么做。该函数是从页面内容中调用的。有一个 PHP for 循环,我可以在其中获取正确的信息,然后将其传递给 Javascript 函数。有没有办法让页面延迟渲染 PHP,直到 API 加载完成?
  • 什么触发了函数调用?文档就绪事件?

标签: javascript google-visualization wkhtmltopdf


【解决方案1】:

谷歌图表一点也不好。我对谷歌图表有很多问题。 我正在使用 D3 库 https://d3js.org v5.9.2。

一切正常。

您可以找到如何做到这一点的示例。 我用了那个例子https://wizardace.com/d3-piechart/

【讨论】:

    【解决方案2】:

    最近遇到了这个问题。我已经尝试了所有解决方法来解决加载问题 - 延迟、setInterval、setTimeout。也尝试升级 wkhtml 版本。

    对我有用的是明确定义要使用的 Google Charts 版本号。就我而言,版本 44。

    <script>google.load("visualization", "44", {packages:["corechart"]});</script>
    

    注意:现在使用版本“1”意味着您正在使用当前版本。根据 Google 文档 - “所有 'jsapi' 请求现在都被重定向到新的加载程序。如果您加载版本 '1' 或 '1.0',您现在将加载 'current'。”

    【讨论】:

    • 我试过 '45' 但没有用,所以 '44' 似乎是一个神奇的数字。
    【解决方案3】:

    我也有使用问题

    window.onload = function () {
       google.charts.load("current", {packages:["corechart", "timeline", "bar"]});
       google.charts.setOnLoadCallback(drawCharts);
    };
    

    drawCharts 不会由 QT 引擎启动,因此不会在 PDF 中呈现图表(也已使用 QTWeb 浏览器验证)。

    我终于用一种不太优雅的方式解决了

    window.onload = function () {
       google.charts.load("current", {packages:["corechart", "timeline", "bar"]});
       setTimeout(function(){drawCharts();}, 500);
    };
    

    【讨论】:

      【解决方案4】:

      问题: 当使用 wkhtmltopdf / wkhtmltoimage html 页面上的 pdf / 图像(使用 Google Chart)时,它不包含 Google 图表。输出(pdf / png)在谷歌图表应该显示的位置只是空白。当然,原始的 html 页面是可以的。

      解决方案: 我通过替换解决了这个问题(Google Charts + wkhtmltopdf):

      <script src="http://www.gstatic.com/charts/loader.js"></script>
      

      通过

      <script src="http://www.google.com/jsapi"></script>
      

      wkhtmltopdf 库不知何故无法处理包含第一个 javascript 包含的 Google Chart html 页面。

      【讨论】:

      • 但是,这样做您将错过 Google Charts API 的任何新功能...
      • 也为我工作。
      • @Adambean 那么解决方案是什么?
      • 如果您想使用较新的 Google Charts API(来自“gstatic.com”),您现在唯一的选择是 PhantomJS(已停产但仍然有效)或 PDFcloud(免费试用积分)。两者都将产生同样出色的结果,尽管 PhantomJS 的设置可能比较棘手。
      【解决方案5】:

      我今天自己解决了这个问题,所以这对我有用。如需更详细的演练,欢迎阅读我的 blog post 关于该主题的内容。

      我只需要进行两个简单的更改即可使其工作:

      1. 提供javascript-delay 参数,例如javascript-delay 1000。这会将 JavaScript 代码的执行延迟 1000 毫秒
      2. 加载 Google Visualization API 时添加回调

      function init() {
        google.load("visualization", "1.1", {
          packages: ["corechart"],
          callback: 'drawCharts'
        });
      }

      然后您可以简单地实现drawCharts 函数,在该函数中您可以像往常一样绘制图表。

      确保您的标记包含以下内容:

      <body onload="init()">
          <div id="my-chart"></div>
      </body>
      

      只需将您的图表绘制到具有上述 ID 的 div 上,您就可以开始了。

      注意:我使用的是最新的可用二进制文件(截至目前为 0.12.0)。在 64 位 Ubuntu 安装上测试。

      【讨论】:

      • 嗨@Andy0708 - 我试过这个方法没有任何运气。在 Ubuntu 14.04.4、Windows 10 和 OSX 10.11.6 上使用最新版本的 wkhtmltopdf 进行了测试 - 你有任何我可以查看的工作示例吗?
      • 我是这样处理这个问题的:github.com/wkhtmltopdf/wkhtmltopdf/issues/…
      【解决方案6】:

      而不是使用javascript-delay 选项,您应该实际等待使用window-status 呈现图表。 window-status 让 wkhtmltopdf 等到窗口状态达到所需的值。

      向图表添加事件监听器

      google.visualization.events.addListener(tableChart, 'ready', myReadyHandler);
      function myReadyHandler(){
        window.status = "ready";
      }
      

      使用--window-status ready运行wkhtmltopdf

      【讨论】:

        【解决方案7】:

        它正在使用以下代码。

        <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
        

        并添加超时/等待直到加载。

         google.charts.load('current', {packages: ['corechart']});
            var interval = setInterval(function() {
              if (
                google.visualization !== undefined
                && google.visualization.DataTable !== undefined
                && google.visualization.PieChart !== undefined
              ){
                clearInterval(interval);
                window.status = 'ready';
                drawCharts();
              }
            }, 100);
        

        【讨论】:

          【解决方案8】:

          如果您在 2020 年 7 月 ~ 5 月之后遇到此问题,并且您的脚本正在运行,但现在没有更多,那么您必须知道为什么 Google 已弃用 http://www.google.com/jsapi 中的脚本版本,现在他们正在重定向对与 wkhtmltopdf 不兼容的http://www.gstatic.com/charts/loader.js 的请求。

          所以,要回到旧版本,你必须像这样改进你的代码:

          <script type="text/javascript" src="http://www.google.com/jsapi"></script>
                  
          <script type="text/javascript">
          function init() {
              //the latest version who worked for me was the 44. 45 and above not worked anymore.
              google.load("visualization", "44", {packages:["corechart"]});
              var interval = setInterval(function() {
                  if ( google.visualization !== undefined && google.visualization.DataTable !== undefined && google.visualization.PieChart !== undefined ){ clearInterval(interval);
                  window.status = 'ready';
                  drawCharts(); //call here your callback who will render the chart
                  }
              }, 100);
          }
          </script>
          

          当 window.status 准备好时,使用这个选项告诉 wkhtmltopdf 开始渲染 pdf:

          --window-status ready

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多