Реализация экспорта графиков/дашбордов в PDF/PNG на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация экспорта графиков/дашбордов в PDF/PNG на сайте
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация экспорта графиков/дашбордов в PDF/PNG на сайте

Экспорт дашборда в PDF или PNG требует захвата DOM-элементов в изображение и генерации документа. Существует два подхода: клиентский (через HTML Canvas API) и серверный (через headless Chromium).

Клиентский экспорт: html2canvas + jsPDF

npm install html2canvas jspdf
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

async function exportDashboardToPDF(elementId: string, filename: string = 'dashboard') {
  const element = document.getElementById(elementId);
  if (!element) return;

  // Показать loader
  const loader = document.createElement('div');
  loader.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.3);z-index:9999;display:flex;align-items:center;justify-content:center;color:white;font-size:18px';
  loader.textContent = 'Генерация PDF...';
  document.body.appendChild(loader);

  try {
    const canvas = await html2canvas(element, {
      scale: 2,          // 2x для чёткости на Retina
      useCORS: true,     // для внешних изображений
      logging: false,
      backgroundColor: '#ffffff'
    });

    const imgData = canvas.toDataURL('image/png');
    const pdf = new jsPDF({
      orientation: canvas.width > canvas.height ? 'landscape' : 'portrait',
      unit: 'px',
      format: [canvas.width / 2, canvas.height / 2]
    });

    pdf.addImage(imgData, 'PNG', 0, 0, canvas.width / 2, canvas.height / 2);
    pdf.save(`${filename}_${format(new Date(), 'yyyy-MM-dd')}.pdf`);

  } finally {
    document.body.removeChild(loader);
  }
}

async function exportToPNG(elementId: string, filename: string = 'chart') {
  const element = document.getElementById(elementId);
  if (!element) return;

  const canvas = await html2canvas(element, { scale: 2, backgroundColor: '#ffffff' });

  const link = document.createElement('a');
  link.download = `${filename}_${format(new Date(), 'yyyy-MM-dd')}.png`;
  link.href = canvas.toDataURL('image/png');
  link.click();
}

React Hook

function useExport(elementRef: React.RefObject<HTMLElement>) {
  const [isExporting, setIsExporting] = useState(false);

  const exportToPDF = async (filename?: string) => {
    if (!elementRef.current || isExporting) return;
    setIsExporting(true);

    try {
      await exportDashboardToPDF(elementRef.current, filename);
    } finally {
      setIsExporting(false);
    }
  };

  const exportToPNG = async (filename?: string) => {
    if (!elementRef.current || isExporting) return;
    setIsExporting(true);

    try {
      const canvas = await html2canvas(elementRef.current, {
        scale: 2, backgroundColor: '#ffffff'
      });
      downloadCanvas(canvas, filename);
    } finally {
      setIsExporting(false);
    }
  };

  return { exportToPDF, exportToPNG, isExporting };
}

// Компонент с кнопками экспорта
function DashboardWithExport() {
  const dashboardRef = useRef<HTMLDivElement>(null);
  const { exportToPDF, exportToPNG, isExporting } = useExport(dashboardRef);

  return (
    <div>
      <div className="flex gap-2 mb-4">
        <button onClick={() => exportToPDF('analytics-report')}
          disabled={isExporting} className="export-btn">
          {isExporting ? '⏳' : '📄'} Экспорт PDF
        </button>
        <button onClick={() => exportToPNG('dashboard')}
          disabled={isExporting} className="export-btn">
          {isExporting ? '⏳' : '🖼'} Сохранить PNG
        </button>
      </div>

      <div ref={dashboardRef} id="dashboard-content">
        <Charts />
      </div>
    </div>
  );
}

Серверный экспорт через Puppeteer

Для сложных дашбордов с SVG/WebGL графиками html2canvas может не справиться. Серверный рендер:

import puppeteer from 'puppeteer';

// POST /api/export/pdf
app.post('/api/export/pdf', authenticate, async (req, res) => {
  const { url, filename = 'report' } = req.body;

  const browser = await puppeteer.launch({ headless: 'new' });
  const page = await browser.newPage();

  // Передать auth cookie
  await page.setCookie({
    name: 'auth_token',
    value: req.token,
    domain: 'your-app.com'
  });

  await page.goto(`${process.env.APP_URL}${url}?export=true`, {
    waitUntil: 'networkidle0',
    timeout: 30000
  });

  // Дождаться рендера графиков
  await page.waitForSelector('[data-loaded="true"]', { timeout: 15000 });

  const pdf = await page.pdf({
    format: 'A4',
    landscape: true,
    printBackground: true,
    margin: { top: '20mm', right: '15mm', bottom: '20mm', left: '15mm' }
  });

  await browser.close();

  res.setHeader('Content-Type', 'application/pdf');
  res.setHeader('Content-Disposition', `attachment; filename="${filename}.pdf"`);
  res.send(pdf);
});

Экспорт данных в CSV/Excel

import * as XLSX from 'xlsx';

function exportToExcel(data: Record<string, unknown>[], filename: string) {
  const worksheet = XLSX.utils.json_to_sheet(data);
  const workbook = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Data');
  XLSX.writeFile(workbook, `${filename}.xlsx`);
}

Сроки

Клиентский экспорт PNG/PDF + кнопки — 1–2 дня. Серверный через Puppeteer — 3–5 дней.