您现在的位置是:网站首页 > 图表导出与打印文章详情

图表导出与打印

数据可视化的输出需求

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图表的打印功能通常有两种方式:

  1. 使用浏览器原生打印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();
}
  1. 将图表转换为图片后打印:
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();
  });
}

导出时的性能优化

当处理大型图表或大量数据导出时,性能优化很重要:

  1. 使用离屏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();
  1. 分步导出复杂图表:
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);
  });
}

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步