23

I'm using the HighCharts library to generate some dynamic charts. However, I'd like to render the HighCharts canvas element as a PNG image, such that the user can copy and paste the chart into an email, etc. without having to use the exporting function.

Specifically, I'm trying to create an HTML email template that includes the chart, and want the user to be able to select all > copy/paste into their email client instead of copy/pasting, exporting the image, then finding a way to insert it in the email.

I've found this: Capture HTML Canvas as gif/jpg/png/pdf?, but the code doesn't seem to render an image to the document.

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Ben Wilson
  • 2,271
  • 3
  • 26
  • 35
  • Recent version of highcharts are rendered using SVG not HTML5 canvas: http://www.highcharts.com/component/content/article/2-news/12-highcharts-goes-svg – Mark Jan 25 '12 at 01:55

4 Answers4

28

Here's a hack if you have your heart set on using HighCharts. It uses canvg to parse the SVG into a canvas and then converts the canvas to a PNG.

chart = new Highcharts.Chart({
    
    chart: {
        renderTo: 'container'
    },
    
    title: {
        text: ''
    },
    
    xAxis: {
        categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    },
    
    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]        
    }],
    
    navigation: {
        buttonOptions: {
            align: 'center'
        }
    }
});

canvg(document.getElementById('canvas'), chart.getSVG())
    
var canvas = document.getElementById("canvas");
var img = canvas.toDataURL("image/png");

document.write('<img src="'+img+'"/>');
Mark
  • 106,305
  • 20
  • 172
  • 230
  • This is awesome; assuming it would be too much to ask to get this working in the POS Internet Explorer. It won't render in Outlook (of course). Thanks again for your help. – Ben Wilson Jan 25 '12 at 17:08
  • I was thinking perhaps I could use a somewhat kludgy method of saving the resultant PNG file to the server, then running a cron script to access the page, so that the updated image would be routinely saved, then I would just load a different page with the image from the server. I found this: http://stackoverflow.com/questions/7291183/decoding-a-canvas-todataurl -- but there's no instruction there about how I would pass the canvas.toDataURL(); output to a PHP variable and save one the server – Ben Wilson Jan 25 '12 at 20:19
  • i am using angular ,while converting i am getting error can you please help http://stackoverflow.com/questions/19245398/how-to-convert-highchart-to-binary-image/19245522?noredirect=1#comment28488385_19245522 – Prashobh Oct 08 '13 at 11:10
11

I know this is now an old question, but since it came up #1 for me in a Google search result, I think it's worth mentioning that Highcharts now natively supports a server-side image generation script and it works great.

jkraybill
  • 3,339
  • 27
  • 32
  • Awesome.... excuse my naivete, but is there some type of instructional guide for setting this up? It looks like this is more an explanation of the tool rather than a setup guide, but maybe I am missing something plainly obvious. – Ben Wilson Mar 04 '13 at 17:19
  • Looks like there isn't a section in the core documentation yet. However, I used the page I referred to as a guide for what to do, and found it VERY easy. All the components are basically configuration-free and it worked as advertised right out of the box. – jkraybill Mar 05 '13 at 00:32
  • If you want more of a how-to, I'd also suggest talking to highcharts support - they're very responsive. – jkraybill Mar 05 '13 at 00:32
  • You're right; very easy to setup in terms of getting the PhantomJS to spit out the images. It would be nice if they had some documentation on in-page rendering, etc. Thanks for your help! – Ben Wilson Mar 05 '13 at 16:21
9

With the information from "Render charts on the server" (from jkraybills answer), I've created this minimal example using a Ajax to get an image of a chart that has not been rendered, and displaying it in an img-tag.

HTML:

<img id="chart" style="width: 600px;" />

Javascript:

// Regular chart options
var options = {
    title: {
        text: 'My chart'
    }
    ...
}

//URL to Highcharts export server
var exportUrl = 'http://export.highcharts.com/';

//POST parameter for Highcharts export server
var object = {
    options: JSON.stringify(options),
    type: 'image/png',
    async: true
};

//Ajax request
$.ajax({
    type: 'post',
    url: exportUrl,
    data: object,
    success: function (data) {
        // Update "src" attribute with received image URL
        $('#chart').attr('src', exportUrl + data);
    }
});

As in this JSFiddle demonstration.

The rest of the POST parameter (width, callback...) are in the documentation.

Halvor Holsten Strand
  • 19,829
  • 17
  • 83
  • 99
6

Here's a server side solution based on PhantomJS. You can use JSONP to make a cross domain call to image.vida.io.

http://image.vida.io/

Your chart/visualization need to be accessible from outside. You can pass credential to the URL.

http://image.vida.io/api/https%3A%2F%2Fvida.io%2Fdocuments%2FWgBMc4zDWF7YpqXGR/viewport_width=980&viewport_height=900&delay=5000&selector=%23canvas

Then you can display image with img tag:

<img src="data:image/png;base64, [base64 data]"/>

It works across browser.

Phuoc Do
  • 1,344
  • 10
  • 14