最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - PhantomJS renders blurry Chart.js canvas - Stack Overflow

programmeradmin9浏览0评论

I'm trying to render a report via PhantomJS 2.1.1 where the HTML page contains a chart generated by Chart.js. I have full control over that page. The resulting PDF should be a printable A4. As you can see in the screenshot down below, the chart is very blurry.

Is there any way I can make either Chart.js or PhantomJS render the chart/page at a higher DPI so that the drawn canvas appears nice and sharp?

PhantomJS:

page.property('paperSize', {
  format: 'A4',
  orientation: 'portrait',
  border: '2cm'
});

Chart.js:

var lineChart = new Chart(ctx).Line(data, {
  animation: false,
  responsive: true,
  pointDot: false,
  scaleShowLabels: true,
  showScale: true,
  showTooltips: false,
  bezierCurve : false,
  scaleShowVerticalLines: false
});

I'm trying to render a report via PhantomJS 2.1.1 where the HTML page contains a chart generated by Chart.js. I have full control over that page. The resulting PDF should be a printable A4. As you can see in the screenshot down below, the chart is very blurry.

Is there any way I can make either Chart.js or PhantomJS render the chart/page at a higher DPI so that the drawn canvas appears nice and sharp?

PhantomJS:

page.property('paperSize', {
  format: 'A4',
  orientation: 'portrait',
  border: '2cm'
});

Chart.js:

var lineChart = new Chart(ctx).Line(data, {
  animation: false,
  responsive: true,
  pointDot: false,
  scaleShowLabels: true,
  showScale: true,
  showTooltips: false,
  bezierCurve : false,
  scaleShowVerticalLines: false
});

Share Improve this question asked Apr 6, 2016 at 7:00 dislickdislick 6771 gold badge7 silver badges25 bronze badges 5
  • What is the height and widh of canvas element? – Rahul R. Commented Apr 6, 2016 at 7:25
  • @RahulR. I've set it to 100% using CSS. I think Chart.js is figuring that out on its own because of responsive: true – dislick Commented Apr 6, 2016 at 7:28
  • did you found a solution for this issue? – aldo.roman.nurena Commented Jul 14, 2016 at 23:34
  • No solution yet. @aldo.roman.nurena – dislick Commented Jul 25, 2016 at 11:43
  • 1 I found this github.com/ariya/phantomjs/pull/14085 It seems they solved it applying a DPI setting but it has not been published yet. It's on master branch, though – aldo.roman.nurena Commented Jul 25, 2016 at 14:54
Add a comment  | 

5 Answers 5

Reset to default 8 +50

Add viewportSize and zoomFactor in your phantomjs page:

await page.property('viewportSize', { height: 1600, width: 3600 });
await page.property('zoomFactor', 4);

and add in your html head template

<script>
  window.devicePixelRatio = 4;
</script>

Try setting the zoom factor using a higher DPI for paper in relation to screen DPI:

page.zoomFactor = 300 / 96;   // or use / 72

Must be set after page size is defined.

You could also check out this answer:
Poor quality of png images drawn into html canvas

For Phantom 2, I rendered the charts with a large canvas to get the resolution up and then converted it into a png finally destroying and removing the old canvas and replacing them with an image with responsive CSS classes. Adjusting the knobes on the canvas width and height in addition to Chart.js options will get you a perfect render. We were able to get our rendering speed up with the approach (alternative to SVG renders) and the file size down.

HTML:

<div class="container">
  <!-- generated images -->
  <img id="someIdImage" class="img-responsive"></img>

  <!-- temporary canvas -->
  <canvas id="someId" width="2000" height="600"></canvas>    
</div>

Javascript:

/**
 * _plot() plot with Chart.js
 *
 * @param {Function} callback
 */
 function _plot(callback) {
  var config = {}; // some Chart.js config
  var id = 'someId';
  var el = document.querySelector('#' + id);
  var el2d = el.getContext('2d');

  // plot instance
  var instance = new Chart(el2d, config);

  // generate and append image
  document.querySelector('#' + id + 'Image').setAttribute('src', el.toDataURL('image/png'));

  // destroy instance
  instance.destroy();
  el.parentElement.removeChild(el);

  // callback
  if (callback) {
    callback();
  }
}

Chart.js now has the parameter "devicePixelRatio". This allows you to increase the resolution directly in Chart.js. (normal 96dpi. target 300dpi; 300/96 = 3.125)

options:{
      devicePixelRatio: 3
}

Documentation: https://www.chartjs.org/docs/3.0.2/configuration/device-pixel-ratio.html

I can confirm that the @DevTrong response is working with Phantomjs 2.1.1

the only difference is that i set in my settings file:

    page.viewportSize = { width: 3600, height: 1600 };
    page.zoomFactor = 4;


Note: Its very important to set in you html this part:

<//script>
  window.devicePixelRatio = 4;
<//script> (fix the script tag)
发布评论

评论列表(0)

  1. 暂无评论