阿里云主机折上折
  • 微信号
Current Site:Index > Export and print charts

Export and print charts

Author:Chuan Chen 阅读数:1413人阅读 分类: ECharts

Exporting and Printing Charts in Data Visualization

ECharts provides multiple ways to export charts as images or PDFs and supports direct printing. These features are highly practical for data sharing, report generation, and offline analysis. Developers can implement complex export requirements through simple configurations.

Exporting as Images

ECharts has built-in image export functionality, allowing you to obtain a chart's base64 URL via the getDataURL() method:

// Get chart instance
const chartInstance = echarts.init(document.getElementById('chart-container'));

// Export as PNG
const pngDataUrl = chartInstance.getDataURL({
  type: 'png',
  pixelRatio: 2,  // Improve export quality
  backgroundColor: '#fff'
});

// Create download link
const link = document.createElement('a');
link.href = pngDataUrl;
link.download = 'chart-export.png';
link.click();

Supported image formats include:

  • png (default)
  • jpeg
  • svg (requires browser support)

Batch Exporting Multiple Charts

Real-world projects often require exporting multiple related charts simultaneously:

// Assume there are multiple chart containers on the page
const chartContainers = [
  '#chart1', 
  '#chart2',
  '#chart3'
];

// Use Promise.all to handle multiple chart exports
Promise.all(chartContainers.map(container => {
  const chart = echarts.init(document.querySelector(container));
  return chart.getDataURL({ type: 'png' });
})).then(urls => {
  urls.forEach((url, index) => {
    const a = document.createElement('a');
    a.href = url;
    a.download = `chart-${index+1}.png`;
    a.click();
  });
});

Exporting as PDF

While ECharts doesn't directly support PDF exports, you can achieve this using libraries like jsPDF:

import jsPDF from 'jspdf';

// First, get the chart image data
const chart = echarts.init(document.getElementById('chart'));
const imgData = chart.getDataURL({ 
  type: 'jpeg',
  quality: 0.95
});

// Create PDF document
const doc = new jsPDF();
doc.addImage(imgData, 'JPEG', 10, 10, 180, 100);
doc.save('chart-export.pdf');

Printing Charts

You can directly call the browser's print API to print charts:

function printChart() {
  const printWindow = window.open('', '_blank');
  const chartHtml = `
    <!DOCTYPE html>
    <html>
      <head>
        <title>Chart Print</title>
        <style>
          body { margin: 0; padding: 20px; }
          #print-chart { 
            width: 100%;
            height: 600px; 
          }
        </style>
      </head>
      <body>
        <div id="print-chart"></div>
        <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
        <script>
          const chart = echarts.init(document.getElementById('print-chart'));
          chart.setOption(${JSON.stringify(chart.getOption())});
          setTimeout(() => window.print(), 500);
        </script>
      </body>
    </html>
  `;
  
  printWindow.document.write(chartHtml);
  printWindow.document.close();
}

Advanced Export Configuration

ECharts allows fine-grained control over the export process:

// Customize export content
chartInstance.getDataURL({
  type: 'png',
  excludeComponents: ['toolbox', 'dataZoom'], // Exclude specific components
  pixelRatio: 3, // High-definition export
  backgroundColor: '#f5f5f5',
  connectedBackgroundColor: '#333' // Connected background color
});

Server-Side Exporting

For scenarios requiring heavy computation or confidentiality, exports can be performed on the server:

// Frontend sends configuration to backend
const exportOnServer = async () => {
  const option = chart.getOption();
  const response = await fetch('/api/export-chart', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ option })
  });
  const blob = await response.blob();
  saveAs(blob, 'server-export.png'); // Using FileSaver.js
};

Export Event Handling

Listen to export-related events to implement custom logic:

chart.on('finished', () => {
  console.log('Chart rendering complete, safe to export');
});

// Custom toolbar button to trigger export
chart.setOption({
  toolbox: {
    feature: {
      myExport: {
        show: true,
        title: 'Custom Export',
        icon: 'path://M...',
        onclick: () => {
          // Custom export logic
        }
      }
    }
  }
});

Export Performance Optimization

Handling performance issues when exporting large datasets:

// Temporarily simplify data to improve export speed
function exportOptimized() {
  const originalOption = chart.getOption();
  
  // Simplify data series
  const simplifiedOption = JSON.parse(JSON.stringify(originalOption));
  simplifiedOption.series.forEach(series => {
    if (series.data && series.data.length > 1000) {
      series.data = downsampleData(series.data, 500);
    }
  });
  
  // Export with simplified configuration
  chart.setOption(simplifiedOption, { silent: true });
  const imgUrl = chart.getDataURL();
  
  // Restore original configuration
  chart.setOption(originalOption, { silent: true });
  
  return imgUrl;
}

// Downsampling function example
function downsampleData(data, maxPoints) {
  if (data.length <= maxPoints) return data;
  const step = Math.floor(data.length / maxPoints);
  return data.filter((_, index) => index % step === 0);
}

Export Style Customization

Ensure exported results match on-screen display:

// Force print styles
function getPrintStyleUrl() {
  const style = document.createElement('style');
  style.innerHTML = `
    @media print {
      body { background: white !important; }
      .chart-container { 
        width: 100% !important; 
        height: auto !important;
      }
    }
  `;
  
  const blob = new Blob([style.innerHTML], { type: 'text/css' });
  return URL.createObjectURL(blob);
}

// Apply print styles
const printWindow = window.open('', '_blank');
printWindow.document.write(`
  <link rel="stylesheet" href="${getPrintStyleUrl()}" />
  <div class="chart-container">${document.getElementById('chart').outerHTML}</div>
`);

Dynamic Watermark Addition

Automatically add watermarks during export:

function exportWithWatermark() {
  const canvas = chart.getDom().querySelector('canvas');
  const ctx = canvas.getContext('2d');
  
  // Add watermark
  ctx.font = '20px Arial';
  ctx.fillStyle = 'rgba(0,0,0,0.1)';
  ctx.rotate(-20 * Math.PI / 180);
  
  for (let i = -5; i < 15; i++) {
    for (let j = -5; j < 15; j++) {
      ctx.fillText('CONFIDENTIAL', i * 200, j * 100);
    }
  }
  
  // Reset transformation
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  
  // Export image with watermark
  return canvas.toDataURL('image/png');
}

Data Processing Before Export

Final data processing before exporting:

function preprocessBeforeExport() {
  const option = chart.getOption();
  
  // 1. Ensure all data labels are visible
  option.series.forEach(series => {
    if (series.label) {
      series.label.show = true;
      series.label.position = 'top';
    }
  });
  
  // 2. Adjust legend position
  if (option.legend) {
    option.legend.top = 'bottom';
  }
  
  // 3. Disable animations to ensure stable export state
  option.animation = false;
  
  // Apply preprocessed configuration
  chart.setOption(option);
  
  // Return Promise to ensure rendering completion
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(chart.getDataURL());
    }, 500);
  });
}

Multi-Theme Exporting

Support exporting charts with different themes for various scenarios:

const themes = {
  light: {
    backgroundColor: '#ffffff',
    textStyle: { color: '#333' }
  },
  dark: {
    backgroundColor: '#1a1a1a',
    textStyle: { color: '#eee' }
  },
  print: {
    backgroundColor: '#fff',
    textStyle: { color: '#000' },
    grid: { borderWidth: 1 }
  }
};

function exportWithTheme(themeName) {
  const originalOption = chart.getOption();
  const theme = themes[themeName] || {};
  
  // Apply theme
  chart.setOption(theme, true);
  
  // Export
  const url = chart.getDataURL();
  
  // Restore original theme
  chart.setOption(originalOption, true);
  
  return url;
}

Export Resolution Control

Set different export qualities for different purposes:

function exportWithQuality(quality) {
  let pixelRatio, type;
  
  switch(quality) {
    case 'low':
      pixelRatio = 1;
      type = 'jpeg';
      break;
    case 'medium':
      pixelRatio = 2;
      type = 'png';
      break;
    case 'high':
      pixelRatio = 3;
      type = 'png';
      break;
    case 'print':
      pixelRatio = 4;
      type = 'png';
      break;
    default:
      pixelRatio = 2;
      type = 'png';
  }
  
  return chart.getDataURL({
    type,
    pixelRatio,
    backgroundColor: '#fff'
  });
}

Export State Preservation and Restoration

Maintain chart state stability during export:

class ChartExporter {
  constructor(chartInstance) {
    this.chart = chartInstance;
    this.originalStates = [];
  }
  
  saveState() {
    this.originalStates.push({
      option: this.chart.getOption(),
      width: this.chart.getDom().style.width,
      height: this.chart.getDom().style.height
    });
  }
  
  restoreState() {
    const state = this.originalStates.pop();
    if (state) {
      this.chart.getDom().style.width = state.width;
      this.chart.getDom().style.height = state.height;
      this.chart.setOption(state.option);
    }
  }
  
  export(config) {
    this.saveState();
    
    // Temporarily adjust dimensions
    if (config.width && config.height) {
      this.chart.getDom().style.width = config.width;
      this.chart.getDom().style.height = config.height;
      this.chart.resize();
    }
    
    return new Promise(resolve => {
      setTimeout(() => {
        const url = this.chart.getDataURL(config);
        this.restoreState();
        resolve(url);
      }, 300);
    });
  }
}

// Usage example
const exporter = new ChartExporter(chart);
exporter.export({
  type: 'png',
  width: '1200px',
  height: '800px'
}).then(url => {
  console.log('Exported with custom size:', url);
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.