Exporting"
(→Size) |
|||
(20 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | = | + | {{ZKChartsEssentialsPageHeader}} |
+ | |||
+ | |||
+ | |||
+ | = Exporting Images/PDF = | ||
== Size == | == Size == | ||
The exported image size in pixel is calculated by: | The exported image size in pixel is calculated by: | ||
− | ''chart width'' | + | ''chart width'' x ''scale'' = exported width |
− | ''chart height'' | + | ''chart height'' x ''scale'' = exported height |
If you do not specify a chart's width and height, ZK Charts exports with the default size: | If you do not specify a chart's width and height, ZK Charts exports with the default size: | ||
Line 12: | Line 16: | ||
* height, '''400 pixels''' | * height, '''400 pixels''' | ||
− | Because of [https://api.highcharts.com/highcharts/exporting.scale the default scale] is '''2''', the exported image will be 1200 pixels (width) | + | Because of [https://api.highcharts.com/highcharts/exporting.scale the default scale] is '''2''', the exported image will be 1200 pixels (width) x 800 pixels (height). |
+ | |||
+ | |||
+ | If you specify a chart's width/height (or hfle/vflex), e.g. 400 pixels wide and 200 pixels high, then exported image will be 800 pixels wide and 400 pixels high. | ||
+ | |||
+ | |||
+ | == Differences between a Chart on Screen and Exported One == | ||
+ | Because the exported size might be different from the chart's size on your screen, so the exported chart image might look different from your screen. | ||
+ | |||
+ | For example, [https://github.com/zkoss/zkchartsessentials/blob/master/src/main/webapp/export-images.zul export-images.zul], '''the original chart on the screen''': | ||
+ | [[File:zkchart-essentials-chart-on-screen.png | 900px | center]] | ||
+ | |||
+ | |||
+ | '''The exported result:''' | ||
+ | [[File:zkchart-essentials-exported-chart.png | 900px | center]] | ||
+ | |||
+ | Differences: | ||
+ | # All x-axis labels are rotated. | ||
+ | # The y-axis tick interval changes. | ||
+ | |||
+ | The differences are caused by the different size between an exported image (600 x 400) and on-screen one (1,540 × 286). Because the exported one is smaller, ZK Chart automatically adjuest axis tick label according to the width/height, so | ||
+ | # It rotates all x-axis labels because the exported chart is narrower. | ||
+ | # The y-axis tick interval changes because the exported chart is shorter. ZK Charts automatically removes some axis labels [https://api.highcharts.com/highcharts/yAxis.tickInterval if they are too dense to be drawn]. | ||
+ | |||
+ | |||
+ | To avoid such image difference generated by auto calculation upon size, you may specify explicit chart options like: | ||
+ | <source lang='java'> | ||
+ | chart.getExporting().setSourceWidth(1500); //fix difference 1. | ||
+ | chart.getYAxis().setTickInterval(10); //fix difference 2. | ||
+ | </source> | ||
+ | |||
+ | == Limitation == | ||
+ | It can't export an HTML image inserted in a chart. | ||
+ | |||
+ | = By JSON, Offline = | ||
+ | {{versionSince| 3.0.2}} | ||
+ | |||
+ | Highcharts provides a [https://www.highcharts.com/docs/export-module/setting-up-the-server node.js export server], and it accepts Charts JSON to produce an image/PDF. You can set the server up in your machine. | ||
+ | By using [https://www.zkoss.org/javadoc/latest/zkcharts/org/zkoss/chart/ChartsEngine.html ChartsEngine], you can get a JSON string after setting data. Besides, using ChartsEngine doesn't require ZK Execution, so you can call its setter API in a separate working thread instead of a servlet thread, no need a HTTP request to a zul. Please see [https://github.com/zkoss/zkchartsessentials/blob/master/src/main/java/org/zkoss/zkcharts/essentials/exporting/ChartsEngineComposer.java ChartsEngineComposer]. | ||
+ | |||
+ | = [https://www.zkoss.org/wiki/Small_Talks/2015/August/An_alternative_idea_of_exporting_ZK_Charts#Steps_to_Export_ZK_Charts Export with ImageMagic] = | ||
+ | |||
+ | |||
+ | = [https://www.zkoss.org/wiki/Small_Talks/2015/August/An_alternative_idea_of_exporting_ZK_Charts#Advanced_Usage_-_Export_multiple_Charts_to_one_File Export Multiple Charts to One File] = | ||
+ | |||
+ | |||
+ | |||
+ | = Custom Exporting Button= | ||
+ | By default, ZK Charts already provide 5 options for exporting a chart. | ||
+ | |||
+ | [[File:zkcharts-essentials-defaultExporting.png | center]] | ||
+ | |||
+ | To create custom exporting button, you have to use [http://api.highcharts.com/highcharts/exporting.buttons exporting buttons options]. Since it also replaces the default button, you need to create default options by yourselves and add extra custom options. Please see the example below: | ||
+ | |||
+ | <source lang='java' highlight='22,23,24,25,26,27,28, 30,31,32'> | ||
+ | public class ExportComposer extends SelectorComposer<Component> { | ||
+ | |||
+ | @Wire | ||
+ | private Charts mychart; | ||
+ | private static final String ON_MY_CUSTOM_ITEM = "onMyCustomItem"; | ||
+ | |||
+ | private SingleValueCategoryModel model = new DefaultSingleValueCategoryModel(); | ||
+ | |||
+ | @Override | ||
+ | public void doAfterCompose(Component comp) throws Exception { | ||
+ | //omitted code... | ||
+ | |||
+ | createCustomExportItems(); | ||
+ | } | ||
+ | |||
+ | private void createCustomExportItems() { | ||
+ | Exporting exporting = mychart.getExporting(); | ||
+ | ExportingButton buttons = exporting.getButtons(); | ||
+ | List<MenuItem> menuItems = new ArrayList<>(); | ||
+ | |||
+ | //effectively disable external export server by setting an alternative URL | ||
+ | exporting.setUrl("/export-server-not-enabled.zul"); | ||
+ | //and disable fallback (e.g. for old browsers) | ||
+ | exporting.addExtraAttr("fallbackToExportServer", new AnyVal(false)); | ||
+ | |||
+ | //optional rebuild the default menu items (as of version 7.2.2.0), otherwise they are replaced | ||
+ | menuItems.add(defaultMenuItem("viewFullscreen", "this.fullscreen=new Highcharts.FullScreen(this.container);")); | ||
+ | menuItems.add(defaultMenuItem("printChart", "this.print();")); | ||
+ | menuItems.add(separator()); | ||
+ | menuItems.add(defaultMenuItem("downloadPNG", "this.exportChartLocal();")); | ||
+ | menuItems.add(defaultMenuItem("downloadJPEG", "this.exportChartLocal({type: \"image/jpeg\"});")); | ||
+ | menuItems.add(defaultMenuItem("downloadPDF", "this.exportChartLocal({type: \"application/pdf\"});")); | ||
+ | menuItems.add(defaultMenuItem("downloadSVG", "this.exportChartLocal({type: \"image/svg+xml\"});")); | ||
+ | menuItems.add(separator()); | ||
+ | //add advanced export options - csv and xls exports | ||
+ | menuItems.add(defaultMenuItem("downloadCSV", "this.downloadCSV()")); | ||
+ | menuItems.add(defaultMenuItem("downloadXLS", "this.downloadXLS()")); | ||
+ | menuItems.add(defaultMenuItem("viewData", "this.viewData()")); | ||
+ | menuItems.add(defaultMenuItem("openInCloud", "this.openInCloud()")); | ||
+ | menuItems.add(separator()); | ||
+ | //add custom menu items (possible at any position in the list) | ||
+ | menuItems.add(customMenuItem("My Custom Item (at Client)", "alert('custom menu item clicked, handled in browser')")); | ||
+ | menuItems.add(customMenuItem("My Custom Item (to Server)", fireServerEventScript(ON_MY_CUSTOM_ITEM))); | ||
+ | buttons.setMenuItems(menuItems); | ||
+ | } | ||
+ | |||
+ | private String fireServerEventScript(String eventName) { | ||
+ | return "var chartsWidget = zk(evt.target).$(); " + | ||
+ | "chartsWidget.fire('" + eventName + "', null, {toServer: true});"; | ||
+ | } | ||
+ | |||
+ | @Listen(ON_MY_CUSTOM_ITEM + " = #mychart") | ||
+ | public void handleMyCustomItem() { | ||
+ | Clients.showNotification("custem menu item clicked, handled on server"); | ||
+ | } | ||
+ | |||
+ | private MenuItem customMenuItem(String text, String onclickJS) { | ||
+ | MenuItem menuItem = new MenuItem(); | ||
+ | menuItem.setText(text); | ||
+ | menuItem.setOnclick(new JavaScriptValue("function(evt) {" + onclickJS + "}")); | ||
+ | return menuItem; | ||
+ | } | ||
+ | |||
+ | private MenuItem defaultMenuItem(String textKey, String onclickJS) { | ||
+ | MenuItem menuItem = new MenuItem(); | ||
+ | menuItem.addExtraAttr("textKey", new AnyVal<String>(textKey)); | ||
+ | menuItem.setOnclick(new JavaScriptValue("function(evt) {" + onclickJS + "}")); | ||
+ | return menuItem; | ||
+ | } | ||
+ | |||
+ | private MenuItem separator() { | ||
+ | MenuItem menuItem = new MenuItem(); | ||
+ | menuItem.addExtraAttr("separator", new AnyVal<Boolean>(true)); | ||
+ | return menuItem; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | * Line 22 ~ 28: add default exporting options | ||
+ | * Line 30: add a custom item that executes JavaScript code. | ||
+ | * Line 31: add a custom item that fires an ZK event to the server and handle it with an event listener, <code>handleMyCustomItem()</code> | ||
+ | |||
+ | The result is: | ||
+ | |||
+ | [[File:zkcharts-essentials-customExporting.png | center]] | ||
+ | |||
+ | = Known Issues = | ||
+ | * [https://tracker.zkoss.org/browse/ZKCHARTS-78 Wrong encoding of Chinese characters in client side PDF export] | ||
− | + | {{ZKChartsEssentialsPageFooter}} |
Latest revision as of 06:49, 14 September 2023
Exporting Images/PDF
Size
The exported image size in pixel is calculated by:
chart width x scale = exported width
chart height x scale = exported height
If you do not specify a chart's width and height, ZK Charts exports with the default size:
- width, 600 pixels
- height, 400 pixels
Because of the default scale is 2, the exported image will be 1200 pixels (width) x 800 pixels (height).
If you specify a chart's width/height (or hfle/vflex), e.g. 400 pixels wide and 200 pixels high, then exported image will be 800 pixels wide and 400 pixels high.
Differences between a Chart on Screen and Exported One
Because the exported size might be different from the chart's size on your screen, so the exported chart image might look different from your screen.
For example, export-images.zul, the original chart on the screen:
The exported result:
Differences:
- All x-axis labels are rotated.
- The y-axis tick interval changes.
The differences are caused by the different size between an exported image (600 x 400) and on-screen one (1,540 × 286). Because the exported one is smaller, ZK Chart automatically adjuest axis tick label according to the width/height, so
- It rotates all x-axis labels because the exported chart is narrower.
- The y-axis tick interval changes because the exported chart is shorter. ZK Charts automatically removes some axis labels if they are too dense to be drawn.
To avoid such image difference generated by auto calculation upon size, you may specify explicit chart options like:
chart.getExporting().setSourceWidth(1500); //fix difference 1.
chart.getYAxis().setTickInterval(10); //fix difference 2.
Limitation
It can't export an HTML image inserted in a chart.
By JSON, Offline
Since 3.0.2
Highcharts provides a node.js export server, and it accepts Charts JSON to produce an image/PDF. You can set the server up in your machine. By using ChartsEngine, you can get a JSON string after setting data. Besides, using ChartsEngine doesn't require ZK Execution, so you can call its setter API in a separate working thread instead of a servlet thread, no need a HTTP request to a zul. Please see ChartsEngineComposer.
Export with ImageMagic
Export Multiple Charts to One File
Custom Exporting Button
By default, ZK Charts already provide 5 options for exporting a chart.
To create custom exporting button, you have to use exporting buttons options. Since it also replaces the default button, you need to create default options by yourselves and add extra custom options. Please see the example below:
public class ExportComposer extends SelectorComposer<Component> {
@Wire
private Charts mychart;
private static final String ON_MY_CUSTOM_ITEM = "onMyCustomItem";
private SingleValueCategoryModel model = new DefaultSingleValueCategoryModel();
@Override
public void doAfterCompose(Component comp) throws Exception {
//omitted code...
createCustomExportItems();
}
private void createCustomExportItems() {
Exporting exporting = mychart.getExporting();
ExportingButton buttons = exporting.getButtons();
List<MenuItem> menuItems = new ArrayList<>();
//effectively disable external export server by setting an alternative URL
exporting.setUrl("/export-server-not-enabled.zul");
//and disable fallback (e.g. for old browsers)
exporting.addExtraAttr("fallbackToExportServer", new AnyVal(false));
//optional rebuild the default menu items (as of version 7.2.2.0), otherwise they are replaced
menuItems.add(defaultMenuItem("viewFullscreen", "this.fullscreen=new Highcharts.FullScreen(this.container);"));
menuItems.add(defaultMenuItem("printChart", "this.print();"));
menuItems.add(separator());
menuItems.add(defaultMenuItem("downloadPNG", "this.exportChartLocal();"));
menuItems.add(defaultMenuItem("downloadJPEG", "this.exportChartLocal({type: \"image/jpeg\"});"));
menuItems.add(defaultMenuItem("downloadPDF", "this.exportChartLocal({type: \"application/pdf\"});"));
menuItems.add(defaultMenuItem("downloadSVG", "this.exportChartLocal({type: \"image/svg+xml\"});"));
menuItems.add(separator());
//add advanced export options - csv and xls exports
menuItems.add(defaultMenuItem("downloadCSV", "this.downloadCSV()"));
menuItems.add(defaultMenuItem("downloadXLS", "this.downloadXLS()"));
menuItems.add(defaultMenuItem("viewData", "this.viewData()"));
menuItems.add(defaultMenuItem("openInCloud", "this.openInCloud()"));
menuItems.add(separator());
//add custom menu items (possible at any position in the list)
menuItems.add(customMenuItem("My Custom Item (at Client)", "alert('custom menu item clicked, handled in browser')"));
menuItems.add(customMenuItem("My Custom Item (to Server)", fireServerEventScript(ON_MY_CUSTOM_ITEM)));
buttons.setMenuItems(menuItems);
}
private String fireServerEventScript(String eventName) {
return "var chartsWidget = zk(evt.target).$(); " +
"chartsWidget.fire('" + eventName + "', null, {toServer: true});";
}
@Listen(ON_MY_CUSTOM_ITEM + " = #mychart")
public void handleMyCustomItem() {
Clients.showNotification("custem menu item clicked, handled on server");
}
private MenuItem customMenuItem(String text, String onclickJS) {
MenuItem menuItem = new MenuItem();
menuItem.setText(text);
menuItem.setOnclick(new JavaScriptValue("function(evt) {" + onclickJS + "}"));
return menuItem;
}
private MenuItem defaultMenuItem(String textKey, String onclickJS) {
MenuItem menuItem = new MenuItem();
menuItem.addExtraAttr("textKey", new AnyVal<String>(textKey));
menuItem.setOnclick(new JavaScriptValue("function(evt) {" + onclickJS + "}"));
return menuItem;
}
private MenuItem separator() {
MenuItem menuItem = new MenuItem();
menuItem.addExtraAttr("separator", new AnyVal<Boolean>(true));
return menuItem;
}
}
- Line 22 ~ 28: add default exporting options
- Line 30: add a custom item that executes JavaScript code.
- Line 31: add a custom item that fires an ZK event to the server and handle it with an event listener,
handleMyCustomItem()
The result is:
Known Issues
< Get Complete Source Code of This Book >