【问题标题】:Converting Chart.js canvas chart to image using .toDataUrl() results in blank image使用 .toDataUrl() 将 Chart.js 画布图表转换为图像会导致空白图像
【发布时间】:2013-11-26 00:02:59
【问题描述】:

我正在使用 Chart.js。我正在尝试通过获取 base 64 字符串将图表转换为图像。教程 (http://www.chartjs.org/docs/) 用了整整 1 行来讨论这个主题:

canvas 元素还允许将内容保存为 base 64 字符串,允许将图表保存为图像。

canvas 元素具有toDataURL 的方法,它返回图像的base64 字符串。但是,当我这样做时,它呈现的图像只是一个具有图表尺寸的透明矩形,并且不包括图表内容。

这是一个小提琴:http://jsfiddle.net/KSgV7/

小提琴中的“图像”带有黑色边框,因此您可以看到它们应该在哪里,因为它们似乎只是一个大的透明块。

有没有人成功地将 Chart.js 图表转换为图像?

【问题讨论】:

标签: javascript html canvas chart.js


【解决方案1】:

Chart.JS API 自发布以来已发生变化,较旧的示例似乎不适用于我。 这是一个适用于较新版本的更新小提琴

HTML:

<body>
    <canvas id="canvas" height="450" width="600"></canvas>
    <img id="url" />
</body>

JS:

function done(){
  alert("haha");
  var url=myLine.toBase64Image();
  document.getElementById("url").src=url;
}

var options = {
  bezierCurve : false,
  animation: {
    onComplete: done
  }
};

var myLine = new 
   Chart(document.getElementById("canvas").getContext("2d"),
     {
        data:lineChartData,
        type:"line",
        options:options
      }
    );

http://jsfiddle.net/KSgV7/585/

【讨论】:

  • 这项工作非常好!谢谢 - 但是您的解释中缺少 标记(不在超链接中),如果您添加此 标记,我会发现您的解释更完整。
  • 我很乐意修复它,但没有得到您所指的两个?
  • 当你写 document.getElementById("url").src=url;您引用了一个带有“url”id 的 html 小部件,但我在您的帖子和之前的任何其他帖子中都没有看到此元素的任何定义。此元素在包含的链接中进行了描述,但未在您的帖子中进行描述。我建议您在 Javascript 代码之前添加此元素。
  • 非常感谢!你帮了我很多! :)
【解决方案2】:

图表似乎是异步的,因此您可能需要在动画完成时提供回调,否则画布将为空。

var options = {
    bezierCurve : false,
    onAnimationComplete: done  /// calls function done() {} at end
};

【讨论】:

  • 就是这样!谢谢!他们应该在 charts.js 文档中引用您。
  • 我正在尝试完全使用它,但我得到的是透明图像。这篇文章中的小提琴也有一个透明的图像
  • 我可以通过在 onAnimationComplete 回调中添加更新图像 src 来修复它
  • 小提琴不起作用”。它不应该工作,它证明了我遇到的问题。
  • @KoU_warch 我能够通过在 onAnimationComplete 回调中添加更新图像 src 来修复它 -- 你是怎么做到的?
【解决方案3】:

您应该改用 Chartjs API 函数toBase64Image() 并在动画完成后调用它。因此:

var pieChart, URI;

var options = {
    animation : {
        onComplete : function(){    
            URI = pieChart.toBase64Image();
        }
    }
};

var content = {
    type: 'pie', //whatever, not relevant for this example
    data: {
        datasets: dataset //whatever, not relevant for this example
    },
    options: options        
};    

pieChart = new Chart(pieChart, content);

示例

你可以检查这个例子并运行它

var chart = new Chart(ctx, {
   type: 'bar',
   data: {
      labels: ['Standing costs', 'Running costs'], // responsible for how many bars are gonna show on the chart
      // create 12 datasets, since we have 12 items
      // data[0] = labels[0] (data for first bar - 'Standing costs') | data[1] = labels[1] (data for second bar - 'Running costs')
      // put 0, if there is no data for the particular bar
      datasets: [{
         label: 'Washing and cleaning',
         data: [0, 8],
         backgroundColor: '#22aa99'
      }, {
         label: 'Traffic tickets',
         data: [0, 2],
         backgroundColor: '#994499'
      }, {
         label: 'Tolls',
         data: [0, 1],
         backgroundColor: '#316395'
      }, {
         label: 'Parking',
         data: [5, 2],
         backgroundColor: '#b82e2e'
      }, {
         label: 'Car tax',
         data: [0, 1],
         backgroundColor: '#66aa00'
      }, {
         label: 'Repairs and improvements',
         data: [0, 2],
         backgroundColor: '#dd4477'
      }, {
         label: 'Maintenance',
         data: [6, 1],
         backgroundColor: '#0099c6'
      }, {
         label: 'Inspection',
         data: [0, 2],
         backgroundColor: '#990099'
      }, {
         label: 'Loan interest',
         data: [0, 3],
         backgroundColor: '#109618'
      }, {
         label: 'Depreciation of the vehicle',
         data: [0, 2],
         backgroundColor: '#109618'
      }, {
         label: 'Fuel',
         data: [0, 1],
         backgroundColor: '#dc3912'
      }, {
         label: 'Insurance and Breakdown cover',
         data: [4, 0],
         backgroundColor: '#3366cc'
      }]
   },
   options: {
      responsive: false,
      legend: {
         position: 'right' // place legend on the right side of chart
      },
      scales: {
         xAxes: [{
            stacked: true // this should be set to make the bars stacked
         }],
         yAxes: [{
            stacked: true // this also..
         }]
      },
      animation : {
         onComplete : done
      }      
   }
});

function done(){
    alert(chart.toBase64Image());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<canvas id="ctx" width="700"></canvas>

【讨论】:

    【解决方案4】:

    您可以使用plugins 访问afterRender 挂钩。

    here 是所有可用的插件api。

    在 html 文件中:

    <html>
      <canvas id="myChart"></canvas>
      <div id="imgWrap"></div>
    </html>
    

    在js文件中:

    var chart = new Chart(ctx, {
      ...,
      plugins: [{
        afterRender: function () {
          // Do anything you want
          renderIntoImage()
        },
      }],
      ...,
    });
    
    const renderIntoImage = () => {
      const canvas = document.getElementById('myChart')
      const imgWrap = document.getElementById('imgWrap')
      var img = new Image();
      img.src = canvas.toDataURL()
      imgWrap.appendChild(img)
      canvas.style.display = 'none'
    }
    

    【讨论】:

      【解决方案5】:

      首先将您的 Chart.js 画布转换为 base64 字符串。

      var url_base64 = document.getElementById('myChart').toDataURL('image/png');

      将其设置为锚标记的 href 属性。

      link.href = url_base64;

      &lt;a id='link' download='filename.png'&gt;Save as Image&lt;/a&gt;

      【讨论】:

        【解决方案6】:

        @EH_warch 您需要使用 Complete 回调来生成您的 base64:

        onAnimationComplete: function(){
            console.log(this.toBase64Image())
        }
        

        如果您看到白色图像,则表示您在完成渲染之前调用了 toBase64Image。

        【讨论】:

          【解决方案7】:

          也可以使用toBase64Image()方法设置动画:false

          var options = {
              bezierCurve : false,
              animation: false
          };
          

          Updated Fiddle

          【讨论】:

            猜你喜欢
            • 2015-01-03
            • 1970-01-01
            • 1970-01-01
            • 2012-09-08
            • 2018-12-30
            • 1970-01-01
            • 1970-01-01
            • 2013-07-21
            • 2015-06-30
            相关资源
            最近更新 更多