Skip to content

导出功能

GanttFlow 支持将甘特图导出为 PNG、PDF 和 Excel 格式,方便生成报告和分享。

导出 PNG

tsx
import React, { useRef } from "react"
import { EnhancedGanttChart } from "@agions/gantt-flow"

function App() {
  const ganttRef = useRef(null)

  const exportPNG = async () => {
    try {
      const dataUrl = await ganttRef.current?.exportAsPNG()
      console.log("PNG 导出成功:", dataUrl)
      
      // 创建下载链接
      const link = document.createElement("a")
      link.href = dataUrl
      link.download = `gantt-${Date.now()}.png`
      link.click()
    } catch (error) {
      console.error("导出失败:", error)
    }
  }

  return (
    <>
      <button onClick={exportPNG}>导出 PNG</button>
      <EnhancedGanttChart ref={ganttRef} tasks={tasks} />
    </>
  )
}

导出 PDF

tsx
const exportPDF = async () => {
  try {
    const blob = await ganttRef.current?.exportAsPDF()
    
    // 创建下载链接
    const url = URL.createObjectURL(blob)
    const link = document.createElement("a")
    link.href = url
    link.download = `gantt-${Date.now()}.pdf`
    link.click()
    
    // 清理
    URL.revokeObjectURL(url)
  } catch (error) {
    console.error("导出失败:", error)
  }
}

导出 Excel

tsx
const exportExcel = async () => {
  try {
    const blob = await ganttRef.current?.exportAsExcel()
    
    const url = URL.createObjectURL(blob)
    const link = document.createElement("a")
    link.href = url
    link.download = `gantt-${Date.now()}.xlsx`
    link.click()
    
    URL.revokeObjectURL(url)
  } catch (error) {
    console.error("导出失败:", error)
  }
}

导出选项

可以自定义导出效果:

typescript
interface ExportOptions {
  /** 背景颜色(默认白色) */
  backgroundColor?: string
  
  /** 内边距(像素) */
  padding?: number
  
  /** 图片清晰度 (1-3),默认 2 */
  scale?: number
  
  /** 图片质量 (0-1),默认 1 */
  quality?: number
  
  /** 导出格式 */
  format?: 'png' | 'jpeg' | 'pdf'
  
  /** 文件名前缀 */
  filename?: string
  
  /** 是否包含表头 */
  includeHeader?: boolean
  
  /** 是否包含图例 */
  includeLegend?: boolean
  
  /** 是否包含今日线 */
  includeTodayLine?: boolean
  
  /** 是否包含网格线 */
  includeGridLines?: boolean
  
  /** Excel 特定:是否包含依赖关系 */
  includeDependencies?: boolean
  
  /** Excel 特定:是否包含进度 */
  includeProgress?: boolean
  
  /** Excel 特定:日期格式 */
  dateFormat?: string
}

使用示例

tsx
const options: ExportOptions = {
  backgroundColor: "#ffffff",
  padding: 40,
  scale: 2,
  quality: 1,
  format: "png",
  filename: "project-gantt",
  includeHeader: true,
  includeLegend: true,
  includeTodayLine: true
}

await ganttRef.current?.exportAsPNG(options)
await ganttRef.current?.exportAsPDF(options)

导出面板 UI

GanttFlow 内置了导出面板组件:

tsx
import { ExportPanel } from "@agions/gantt-flow"

<EnhancedGanttChart tasks={tasks}>
  <ExportPanel
    position="top-right"
    showFormats={["png", "pdf", "excel"]}
    buttonText="导出"
    dropdownStyle={{ zIndex: 100 }}
  />
</EnhancedGanttChart>

ExportPanel Props

属性类型默认值说明
position'top-right' | 'top-left' | 'bottom-right' | 'bottom-left''top-right'位置
showFormats('png' | 'pdf' | 'excel')[]['png', 'pdf', 'excel']显示的格式
buttonTextstring'导出'按钮文字
optionsExportOptions{}导出选项

工具栏示例

tsx
import React, { useRef } from "react"
import { EnhancedGanttChart } from "@agions/gantt-flow"
import "@agions/gantt-flow/style"

function ProjectGantt() {
  const ganttRef = useRef(null)

  const handleExport = async (format: 'png' | 'pdf' | 'excel') => {
    const options = {
      backgroundColor: "#ffffff",
      scale: 2,
      filename: `gantt-${format}`
    }
    
    try {
      switch (format) {
        case 'png':
          const pngData = await ganttRef.current?.exportAsPNG(options)
          downloadFile(pngData, `${options.filename}.png`)
          break
        case 'pdf':
          const pdfBlob = await ganttRef.current?.exportAsPDF(options)
          downloadBlob(pdfBlob, `${options.filename}.pdf`)
          break
        case 'excel':
          const excelBlob = await ganttRef.current?.exportAsExcel({
            includeDependencies: true,
            includeProgress: true
          })
          downloadBlob(excelBlob, `${options.filename}.xlsx`)
          break
      }
    } catch (error) {
      console.error('导出失败:', error)
      alert('导出失败,请重试')
    }
  }

  const downloadFile = (dataUrl: string, filename: string) => {
    const link = document.createElement('a')
    link.href = dataUrl
    link.download = filename
    link.click()
  }

  const downloadBlob = (blob: Blob, filename: string) => {
    const url = URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = filename
    link.click()
    URL.revokeObjectURL(url)
  }

  return (
    <div className="gantt-container">
      {/* 工具栏 */}
      <div className="toolbar">
        <h2>项目甘特图</h2>
        <div className="toolbar-actions">
          <button onClick={() => ganttRef.current?.fitToScreen()}>
            适应屏幕
          </button>
          <button onClick={() => handleExport('png')}>
            📷 PNG
          </button>
          <button onClick={() => handleExport('pdf')}>
            📄 PDF
          </button>
          <button onClick={() => handleExport('excel')}>
            📊 Excel
          </button>
        </div>
      </div>

      {/* 甘特图 */}
      <div style={{ height: "calc(100vh - 120px)" }}>
        <EnhancedGanttChart ref={ganttRef} tasks={tasks} />
      </div>
    </div>
  )
}

导出样式优化

暗色主题导出

tsx
// 临时切换到亮色主题再导出
const exportWithLightTheme = async () => {
  // 切换到亮色
  ganttRef.current?.setTheme('light')
  
  // 等待渲染完成
  await new Promise(resolve => setTimeout(resolve, 100))
  
  // 导出
  const dataUrl = await ganttRef.current?.exportAsPNG({
    backgroundColor: '#ffffff'
  })
  
  // 恢复原主题
  ganttRef.current?.setTheme('dark')
  
  downloadFile(dataUrl, 'gantt-light.png')
}

自定义水印

tsx
const exportWithWatermark = async () => {
  const dataUrl = await ganttRef.current?.exportAsPNG()
  
  // 使用 canvas 添加水印
  const img = new Image()
  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 = '24px Arial'
    ctx!.fillStyle = 'rgba(0, 0, 0, 0.2)'
    ctx!.fillText('GanttFlow', img.width - 120, img.height - 20)
    
    // 下载
    const watermarkedUrl = canvas.toDataURL('image/png')
    downloadFile(watermarkedUrl, 'gantt-watermarked.png')
  }
  img.src = dataUrl
}

注意事项

WARNING

  1. 异步操作:导出是异步的,确保在导出完成后再进行其他操作
  2. 大数据量:任务数量很多时,导出可能需要几秒钟
  3. 跨域问题:如果图片包含跨域资源,需要配置 CORS
  4. 内存占用:高清晰度导出会占用较多内存,注意设备性能

下一步

基于 MIT 许可证发布