Exporting Charts

amCharts 4 has exporting functionality built right into its core. It allows saving chart view or its data into various formats, like JPEG, PNG, PDF, XLSX, CSV, or JSON.

This article is dedicated on how to enable this functionality for chart users, as well as do deeper integrations using API.

Export menu

Enabling

Even though export functionality is built-in, the end-user controls - menu - are not enabled by default.

To enable it, you will need to assign an instance of ExportMenu to chart's exporting.menu property:

chart.exporting.menu = new am4core.ExportMenu();
chart.exporting.menu = new am4core.ExportMenu();
{
  // ...
  "exporting": {
    "menu": {
      // No need to specify `type`, since
      // there's only one type of `ExportMenu`
    }
  }
}

Let's take a very basic chart and see how it looks like:

See the Pen amCharts V4: Export (1) by amCharts (@amcharts) on CodePen.24419

You can see a somewhat dimmed out button in the upper right corner, that when hovered will display export options for various image and data formats, as well as print.

Export menu

If you want, you can leave it at it - it's fully functional.

Positioning

By default, menu is placed in the upper-right corner of your chart.

It's easy to re-position it using two of the menu's settings: align and verticalAlign.

align controls horizontal positioning and accepts following values: "left", "middle", and "right" (default).

verticalAlign controls vertical positioning of the legend with the following options for its value: "top" (default), "middle", and "bottom";

These settings will also affect how the menu looks like and opens up.

Let's see how it goes if we place it in the top-left corner using this code:

chart.exporting.menu = new am4core.ExportMenu();
chart.exporting.menu.align = "left";
chart.exporting.menu.verticalAlign = "top";
chart.exporting.menu = new am4core.ExportMenu();
chart.exporting.menu.align = "left";
chart.exporting.menu.verticalAlign = "top";
{
  // ...
  "exporting": {
    "menu": {
      "align": "left",
      "verticalAlign": "bottom"
    }
  }
}

See the Pen amCharts V4: Export (2) by amCharts (@amcharts) on CodePen.24419

Go ahead, hover on the export button to see how menu items have re-arranged themselves to accommodate for the new position.

Styling

A default styling to export menu is automatically applied by creating relative stylesheets on the web page. No additional configuration necessary.

However, if you'd like to modify certain style aspect of the menu, you easily override it using your own custom CSS.

Let's add a custom border around menu items as an example:

.amcharts-amexport-item {
  border: 2px solid #777;
}

.amcharts-amexport-top .amcharts-amexport-item > .amcharts-amexport-menu {
  top: -3px!important;
  left: 2px
}

See the Pen amCharts V4: Export (3) by amCharts (@amcharts) on CodePen.24419

NOTE To override certain default styles, you may need to use CSS' !important directive.

Or, if you'd like to style the whole menu yourself, you can easily disable built-in styling by setting menu's defaultStyles to false.

Modifying menu items

In case you'd like to modify which items are displayed in menu and what order they are displayed in, you can use menu's items.

It's an object resembling nested structure of the menu. Each item in the menu should conform to the IExportMenuItem interface.

Here's how default items looks like:

[
  {
    "label": "...",
    "menu": [
      {
        "label": "Image",
        "menu": [
          { "type": "png", "label": "PNG" },
          { "type": "jpg", "label": "JPG" },
          { "type": "gif", "label": "GIF" },
          { "type": "svg", "label": "SVG" },
          { "type": "pdf", "label": "PDF" }
        ]
      }, {
        "label": "Data",
        "menu": [
          { "type": "json", "label": "JSON" },
          { "type": "csv", "label": "CSV" },
          { "type": "xlsx", "label": "XLSX" }
        ]
      }, {
        "label": "Print", "type": "print"
      }
    ]
  }
]

As you can see, each item contains label, which indicates what will be displayed in the menu.

If item contains sub-items, it also contains menu, which is an array of other menu items.

And finally, if this item is supposed to export stuff to some format, it will also have type property.

OK, so let's try to simplify our export menu to 1-level list, with just three options to export to PNG, save JSON data, and print:

chart.exporting.menu.items = [{
  "label": "...",
  "menu": [
    { "type": "png", "label": "PNG" },
    { "type": "json", "label": "JSON" },
    { "label": "Print", "type": "print" }
  ]
}];
chart.exporting.menu.items = [{
  "label": "...",
  "menu": [
    { "type": "png", "label": "PNG" },
    { "type": "json", "label": "JSON" },
    { "label": "Print", "type": "print" }
  ]
}];
{
  // ...
  "exporting": {
    "menu": {
      // ...
      "items": [{
        "label": "...",
        "menu": [
          { "type": "png", "label": "PNG" },
          { "type": "json", "label": "JSON" },
          { "label": "Print", "type": "print" }
        ]
      }]
    }
  }
}

Let's check if it worked:

See the Pen amCharts V4: Export (4) by amCharts (@amcharts) on CodePen.24419

Adding custom items

As we mentioned in previous chapters, all items for the Export menu are located in its items property, which is a multi-level object.

If we'd like to add a custom item, all we have to do is to push its definition in items.

For custom items in menu, we have to set their type to "custom", e.g.:

chart.exporting.menu.items[0].menu.push({
  label: "Hello",
  type: "custom"
});
chart.exporting.menu.items[0].menu.push({
  label: "Hello",
  type: "custom"
});
{
  // ...
  "exporting": {
    "menu": {
      // ...
      "callback": function(target) {
        chart.exporting.menu.items[0].menu.push({
          label: "Hello",
          type: "custom"
        });
      }
    }
  }
}

That will add the item with a label, but, in order for it do something, we also need to specify a callback function to be called on click. That is done with item's options:

chart.exporting.menu.items[0].menu.push({
  label: "Hello",
  type: "custom",
  options: {
    callback: function() {
      console.log("Hello back at ya!");
    }
  }
});
chart.exporting.menu.items[0].menu.push({
  label: "Hello",
  type: "custom",
  options: {
    callback: function() {
      console.log("Hello back at ya!");
    }
  }
});
{
  // ...
  "exporting": {
    "menu": {
      // ...
      "callback": function(target) {
        chart.exporting.menu.items[0].menu.push({
          label: "Hello",
          type: "custom",
          options: {
            callback: function() {
              console.log("Hello back at ya!");
            }
          }
        });
      }
    }
  }
}

See the Pen amCharts 4: Adding custom item to export menu by amCharts (@amcharts) on CodePen.24419

Export options

There are a few options you can set. For the complete list, check out Export class reference.

Let's take a short look at a few important ones.

Property Type Default Comment
backgroundColor Color - Export will try to determine what background your chart is on, whether it's set directly on a chart container, or comes from its parent containers, all the way to the body of the document.

If you'd rather have a specific color as a background, set backgroundColor.

TIP To make background transparent, set it to am4core.color("#f00", 0) (opacity 0)

dataFields Object {} (empty object) When exporting data, columns/fields will be named as their respective keys in data.

dataFields allows a) to specify which fields to export; (only fields included in dataFields will be exported if its set) b) how to name respective fields in exported formats.

dateFields string[] [] (empty array) Lists which fields in data are dates.

If set, those fields will be formatted accordingly when exporting in certain data formats.

dateFormat string - If set, this format will be used to format dates from dateFields. (more about date formatting)

If not set, chart's dateFormatter will be used instead.

filePrefix string "amCharts" If you'd like exported files to have certain prefix, set it here.

E.g. setting to "myExport", will make export save files as "myExport.png", "myExport.json", etc.

title string Chart title When printing the chart, export will try to use chart's title as printed documents title.

If you'd like to use something else, set title.

useRetina boolean true Sets whether images can be exported larger than they really are in order not to lose any detail.
useWebFonts boolean true Sets whether export should attempt to load web font information so that charts are exported using them.

Each of those settings are set on chart's Export object, accessible via exporting property, e.g.:

chart.exporting.filePrefix = "myExport";
chart.exporting.useWebFonts = false;
chart.exporting.filePrefix = "myExport";
chart.exporting.useWebFonts = false;
{
  // ...
  "exporting": {
    "filePrefix": "myExport",
    "useWebFonts": false
  }
}

Excluding elements from export

It's possible to exclude certain elements from exported images. In fact, some of the elements, like grip buttons of scrollbars and the zoom out button, are excluded by default.

To prevent an element from making into exported image, set its exportable setting to false.

Want to disable whole scrollbar from appearing in exports (not just its grips)?

chart.scrollbarX.exportable = false;
chart.scrollbarX.exportable = false;
{
  // ...
  "scrollbarX": {
    "type": "Scrollbar",
    "exportable": false
  }
}

Don't want series' tooltips in your images?

series.tooltip.exportable = false;
series.tooltip.exportable = false;
{
  // ...
  "series": [{
    // ...
    "tooltip": {
      "exportable": false
    }
  }]
}

You get the drift.

Format-specific options

Each export type has a set of options that affect how exported image looks, or how data is formatted.

Some examples of format-specific options: quality of the JPEG image, separator used in exported PDF, etc.

Getting current options

To get currently set (or default) options for the specific format, we can use Export's getFormatOptions(format) method.

For example the calling chart.exporting.getFormatOptions("jpg") will return the following options object:

{
  quality: 0.8
}

Setting options

To set options for the specific format we can use setFormatOptions(format, options) method.

The following code will modify quality setting for the JPEG exports:

let options = chart.exporting.getFormatOptions("jpg");
options.quality = 0.5;
chart.exporting.setFormatOptions("jpg", options);
var options = chart.exporting.getFormatOptions("jpg");
options.quality = 0.5;
chart.exporting.setFormatOptions("jpg", options);

Options via menu

Format-specific options can be set via Export menu items as well.

We have looked at the configuration of menu earlier in this article. Besides listed menu item properties, you can also set options for the format, using options key:

chart.exporting.menu.items = [{
  "label": "...",
  "menu": [
    { "type": "png", "label": "PNG", "options": { "quality": 1 } },
    { "type": "json", "label": "JSON", "options": { "indent": 2, "useTimestamps": true } },
    { "label": "Print", "type": "print" }
  ]
}];
chart.exporting.menu.items = [{
  "label": "...",
  "menu": [
    { "type": "png", "label": "PNG", "options": { "quality": 1 } },
    { "type": "json", "label": "JSON", "options": { "indent": 2, "useTimestamps": true } },
    { "label": "Print", "type": "print" }
  ]
}];
{
  // ...
  "exporting": {
    "menu": {
      // ...
      "items": [{
        "label": "...",
        "menu": [
          { "type": "png", "label": "PNG", "options": { "quality": 1 } },
          { "type": "json", "label": "JSON", "options": { "indent": 2, "useTimestamps": true } },
          { "label": "Print", "type": "print" }
        ]
      }]
    }
  }
}

List of options

Available options for each format are defined by format-specific interfaces.

Below is a list of formats linked to their options interface.

Interface Format Comment
IExportImageOptions "jpg", "png", "gif" All bitmap images.
IExportSVGOptions "svg" SVG images.
IExportPDFOptions "pdf" PDF documents.
IExportCSVOptions "csv" Exported data in CSV format.
IExportJSONOptions "json" Exported data in JSON format.
IExportExcelOptions "xlsx" Exported data in Excel format.
IExportPrintOptions "print" Chart print.

Using export API

So far we have been using Export menu. It's time to look into how you can tap into chart's export capabilities using the API.

Triggering export

Suppose we want to use some external controls or code to trigger export of the chart.

For that we can use exporting.export(type, config) method.

It's really really easy:

chart.exporting.export("png");
chart.exporting.export("png");

If I wanted I could pass in custom options for the particular format as a second parameter.

Here's an example that has HTML button that triggers custom export function:

See the Pen amCharts V4: Export (5) by amCharts (@amcharts) on CodePen.24419

Getting raw data

If, instead of initiating a download, you'd rather get image (or other format) data as a variable, for subsequent processing, AJAX-uploading to server, or something else, you can use one of the get* methods.

For example to get Base64-encoded PNG data, you'd do this:

let imgData = chart.exporting.getImage("png");
var imgData = chart.exporting.getImage("png");

As with export(), "get" functions can accept options as well.

But, wait, there's one caveat, though.

Image export operations are asynchronous, which means that the function fill finish before image data is generated, and will not return image data, but rather a "Promise".

MORE INFO Read this Mozilla article about concept of Promises.

In environments that support Promises like TypeScript, you could use full arsenal of Promise syntax, like the await directive:

let imgData = await chart.exporting.getImage("png");
console.log(imgData); // contains exported image data

For consistency with regular JavaScript, you can still use Promise then() callback:

chart.exporting.getImage("png").then(function(imgData) {
  console.log(imgData); // contains exported image data
});

Promises is a very powerful concept. You can combine and sync multiple asynchronous calls. You can cancel function operation. And much more.

Common pitfalls

Tainted images

Due to browser's security restrictions, it won't allow exporting charts that have "tainted" images in it.

A "tainted" image is any asset that came from a different domain than the web page displaying the chart. For example, if you load an image bullet from a different domain, and use it on your chart, this would ruin the whole export operation.

For this reason, Export will try to proactively remove all such assets from the chart before trying to export it.

If you'd like to disable removal of tainted images, you can set keepTainted = true via format export options. E.g.:

let options = chart.exporting.getFormatOptions("jpg");
options.keepTainted = true;
chart.exporting.setFormatOptions("jpg", options);
var options = chart.exporting.getFormatOptions("jpg");
options.keepTainted = true;
chart.exporting.setFormatOptions("jpg", options);

Local files

Again, due to security measures, implemented in all modern browsers, export won't work when loaded locally, via file:///.

In order for export to work properly, the web page needs to be loaded via web server, even if it's http://localhost/....

Web fonts

Normally, the export will try to load and use web fonts when exporting the charts. This is done so that if your chart uses web fonts, such as Google Fonts, export looks as close to the original as possible.

However, some web font providers, prohibit such download. If yours does not allow dynamic download, the charts will be exported using default fonts.

On the other hand, if you know you don't use web fonts in charts, you might want to disable this feature to avoid unnecessary operations. To do that, simply set useWebFonts = false in chart.exporting.