您现在的位置是:网站首页 > 图表导出与打印文章详情
图表导出与打印
陈川
【
ECharts
】
51082人已围观
9282字
数据可视化的输出需求
ECharts作为一款强大的数据可视化库,不仅能在网页上展示精美的图表,还经常需要将图表导出为图片或PDF格式,或者直接打印出来。这些功能在报表生成、数据分享等场景中尤为重要。
导出为图片
ECharts提供了多种导出图片的方式,最常用的是调用getDataURL()
方法获取图表的基础64编码图片数据。
// 获取ECharts实例
const myChart = echarts.init(document.getElementById('main'));
// 导出为PNG图片
const imgData = myChart.getDataURL({
type: 'png',
pixelRatio: 2, // 导出图片的分辨率比例,默认为1
backgroundColor: '#fff' // 背景色
});
// 创建一个下载链接
const link = document.createElement('a');
link.href = imgData;
link.download = 'chart.png';
link.click();
对于更复杂的导出需求,可以使用getConnectedDataURL()
方法导出多个关联的图表:
// 导出多个关联图表
const group = new echarts.connect([chart1, chart2]);
const imgData = echarts.getInstanceByDom(document.getElementById('main'))
.getConnectedDataURL('png', {
connectedGroup: group
});
导出为PDF
虽然ECharts本身不直接支持PDF导出,但可以借助第三方库如jsPDF实现:
import jsPDF from 'jspdf';
// 先获取图表图片数据
const imgData = myChart.getDataURL({
type: 'jpeg',
quality: 0.95
});
// 创建PDF文档
const doc = new jsPDF('p', 'mm', 'a4');
doc.addImage(imgData, 'JPEG', 10, 10, 190, 100);
doc.save('chart.pdf');
打印功能实现
实现ECharts图表的打印功能通常有两种方式:
- 使用浏览器原生打印API:
function printChart() {
const printWindow = window.open('', '_blank');
printWindow.document.write(`
<html>
<head>
<title>打印图表</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
</head>
<body>
<div id="printChart" style="width:800px;height:600px;"></div>
<script>
const chart = echarts.init(document.getElementById('printChart'));
chart.setOption(${JSON.stringify(myChart.getOption())});
setTimeout(() => window.print(), 500);
</script>
</body>
</html>
`);
printWindow.document.close();
}
- 将图表转换为图片后打印:
function printChartAsImage() {
const imgData = myChart.getDataURL({
type: 'png',
pixelRatio: 3
});
const printWindow = window.open('', '_blank');
printWindow.document.write(`<img src="${imgData}" style="max-width:100%;">`);
printWindow.document.close();
setTimeout(() => printWindow.print(), 500);
}
导出配置优化
为了获得更好的导出效果,通常需要对图表进行一些特殊配置:
const option = {
// 导出时使用的特殊配置
export: {
// 导出时隐藏工具栏
toolbox: {
show: false
},
// 调整图例位置
legend: {
top: 'bottom'
},
// 增大字体大小
textStyle: {
fontSize: 14
}
},
// 正常显示配置
display: {
toolbox: {
show: true
},
legend: {
right: 10,
top: 'center'
},
textStyle: {
fontSize: 12
}
}
};
// 在导出前应用导出配置
function beforeExport() {
myChart.setOption(option.export);
}
// 导出后恢复显示配置
function afterExport() {
myChart.setOption(option.display);
}
批量导出多个图表
对于需要批量导出多个图表的场景,可以创建一个队列处理:
async function exportMultipleCharts(charts, format = 'png') {
const results = [];
for (const chart of charts) {
const imgData = await new Promise(resolve => {
setTimeout(() => {
resolve(chart.getDataURL({ type: format }));
}, 200); // 添加延迟避免渲染冲突
});
results.push(imgData);
}
return results;
}
// 使用示例
const charts = [chart1, chart2, chart3];
exportMultipleCharts(charts).then(images => {
images.forEach((img, i) => {
const link = document.createElement('a');
link.href = img;
link.download = `chart_${i+1}.png`;
link.click();
});
});
导出SVG格式
ECharts也支持导出为矢量图SVG格式,适合需要无损缩放或后期编辑的场景:
const svgData = myChart.getDataURL({
type: 'svg',
excludeComponents: ['toolbox'] // 排除不需要导出的组件
});
// 处理SVG数据
const svgBlob = new Blob([svgData], {type: 'image/svg+xml'});
const svgUrl = URL.createObjectURL(svgBlob);
const link = document.createElement('a');
link.href = svgUrl;
link.download = 'chart.svg';
link.click();
服务器端导出
对于复杂的导出需求或大量数据的处理,可以考虑使用服务器端导出方案:
// 客户端代码
function exportOnServer(chart) {
const option = chart.getOption();
const canvas = chart.getDom().querySelector('canvas');
const imageData = canvas.toDataURL('image/png');
fetch('/api/export-chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
option: option,
image: imageData
})
})
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'server-export.pdf';
a.click();
});
}
导出时的性能优化
当处理大型图表或大量数据导出时,性能优化很重要:
- 使用离屏Canvas预渲染:
const offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 2000;
offscreenCanvas.height = 1500;
const offscreenChart = echarts.init(offscreenCanvas);
// 设置相同的option
offscreenChart.setOption(myChart.getOption());
// 导出离屏图表
const imgData = offscreenChart.getDataURL();
- 分步导出复杂图表:
async function exportComplexChart() {
// 先导出主图表
const mainImg = myChart.getDataURL();
// 隐藏主图表显示细节图表
myChart.setOption({ series: [{ type: 'line' }] }, { lazyUpdate: true });
const detailImg = myChart.getDataURL();
// 合并图片
const finalCanvas = document.createElement('canvas');
// ... 合并逻辑
return finalCanvas.toDataURL();
}
自定义导出处理器
对于特殊需求,可以创建自定义导出处理器:
class CustomExporter {
constructor(chart) {
this.chart = chart;
}
async exportHighQuality() {
const originalOption = this.chart.getOption();
// 创建高质量配置
const hqOption = JSON.parse(JSON.stringify(originalOption));
hqOption.animation = false;
hqOption.series.forEach(s => {
s.progressive = 0;
s.progressiveThreshold = 0;
});
// 使用离屏Canvas
const canvas = document.createElement('canvas');
canvas.width = originalOption.grid[0].width * 2 || 2000;
canvas.height = originalOption.grid[0].height * 2 || 1500;
const hqChart = echarts.init(canvas);
hqChart.setOption(hqOption);
return new Promise(resolve => {
setTimeout(() => {
resolve(hqChart.getDataURL({ type: 'png', pixelRatio: 1 }));
}, 1000);
});
}
}
// 使用示例
const exporter = new CustomExporter(myChart);
exporter.exportHighQuality().then(imgData => {
// 处理高质量图片
});
导出时的交互处理
在导出过程中处理用户交互和状态保存:
function exportWithInteractivity() {
// 保存当前状态
const originalOption = myChart.getOption();
const originalTooltip = myChart.getModel().getComponent('tooltip');
// 禁用交互
myChart.setOption({
tooltip: { show: false },
dataZoom: { disabled: true },
brush: { disabled: true }
}, { silent: true });
// 获取静态图片
const imgData = myChart.getDataURL();
// 恢复交互
myChart.setOption(originalOption, { replaceMerge: ['tooltip', 'dataZoom', 'brush'] });
return imgData;
}
导出地图时的特殊处理
对于地图图表,导出时需要特别注意:
function exportMapChart() {
// 确保地图资源已加载
return new Promise(resolve => {
if (myChart.getModel().getComponent('geo')) {
const geo = myChart.getModel().getComponent('geo').coordinateSystem;
if (geo && !geo._map) {
myChart.on('rendered', () => {
resolve(myChart.getDataURL());
});
return;
}
}
resolve(myChart.getDataURL());
});
}
导出时的水印添加
在导出的图片上添加水印:
function exportWithWatermark() {
const imgData = myChart.getDataURL();
const img = new Image();
img.src = imgData;
return new Promise(resolve => {
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
// 绘制图表
ctx.drawImage(img, 0, 0);
// 添加水印
ctx.font = '20px Arial';
ctx.fillStyle = 'rgba(0,0,0,0.1)';
ctx.rotate(-20 * Math.PI / 180);
for (let x = -100; x < canvas.width; x += 200) {
for (let y = -50; y < canvas.height; y += 100) {
ctx.fillText('CONFIDENTIAL', x, y);
}
}
resolve(canvas.toDataURL('image/png'));
};
});
}
导出时的多语言处理
对于多语言应用,导出时需要处理文本内容:
function exportWithLocale(locale) {
const originalLocale = echarts.getLocale();
echarts.registerLocale(locale, localeData[locale]);
echarts.setLocale(locale);
// 重新设置选项以应用语言
const option = myChart.getOption();
myChart.setOption(option);
// 导出
const imgData = myChart.getDataURL();
// 恢复语言
echarts.setLocale(originalLocale);
myChart.setOption(option);
return imgData;
}
导出时的主题应用
在导出时应用不同的主题:
function exportWithTheme(themeName) {
// 注册并应用主题
const theme = themes[themeName];
echarts.registerTheme(themeName, theme);
// 创建新实例应用主题
const tempDom = document.createElement('div');
tempDom.style.width = '1000px';
tempDom.style.height = '800px';
tempDom.style.position = 'absolute';
tempDom.style.left = '-9999px';
document.body.appendChild(tempDom);
const tempChart = echarts.init(tempDom, themeName);
tempChart.setOption(myChart.getOption());
return new Promise(resolve => {
setTimeout(() => {
const imgData = tempChart.getDataURL();
document.body.removeChild(tempDom);
resolve(imgData);
}, 500);
});
}