You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jsPDF生成可选中文本PDF失败,寻求代码修改方案

解决React组件生成可选中文本PDF的方案

问题根源

你当前的代码通过html2canvas把整个React组件转为图片后插入PDF,导致所有内容都是位图,无法选中文本。要实现可选中的文本,需要将文本、表格内容以矢量PDF元素插入,仅将图表转为图片嵌入。

修改方案

步骤1:拆分Ref引用

给文本/表格区域和图表区域分别添加独立的ref,方便单独处理:

// 组件内新增两个ref
const contentRef = useRef();
const chartRef = useRef();

在JSX中对应绑定:

// 文本表格区域绑定contentRef
<Col ref={contentRef}>
  {/* 原有文本、表格内容 */}
</Col>

// 图表组件绑定chartRef
<HighchartsReact 
  highcharts={Highcharts} 
  options={ecommercePieChartOptions} 
  ref={chartRef}
/>

步骤2:重写downloadPDF函数

替换原有函数,分别处理可选中的文本内容和需要转图片的图表:

const downloadPDF = async () => {
  const pdf = new jsPDF('p', 'mm', 'a4');
  const pageWidth = pdf.internal.pageSize.getWidth();

  // 1. 渲染文本和表格(生成可选中的PDF内容)
  await pdf.html(contentRef.current, {
    x: 10,
    y: 10,
    width: pageWidth - 20, // 预留左右边距
  });

  // 2. 处理图表为图片插入PDF
  const chartCanvas = await html2canvas(chartRef.current.container);
  const chartImgData = chartCanvas.toDataURL('image/png');
  const chartWidth = pageWidth / 2 - 20; // 匹配原页面Col宽度
  const chartHeight = chartCanvas.height * chartWidth / chartCanvas.width;

  // 将图表插入到页面右侧(对应原布局)
  pdf.addImage(chartImgData, 'PNG', pageWidth/2 + 10, 30, chartWidth, chartHeight);

  // 3. 添加额外页面(原有逻辑保留,文本可选中)
  pdf.addPage();
  pdf.setFontSize(10);
  pdf.text("Conclusion", 10, 10);
  pdf.text("This is a conclusion section with some insights and final thoughts about the E-commerce market trends in India.", 10, 20);

  pdf.addPage();
  pdf.setFontSize(10);
  pdf.text("Content Page", 10, 10);
  pdf.text("Here you can describe the document's structure or provide any additional information.", 10, 20);

  pdf.save('ecommerce-in-india-report.pdf');
};

步骤3:清理冗余代码

移除原有的componentRef及对应useEffect逻辑(若不需要外部调用generatePDF),或按需调整外部调用逻辑。

完整修改后的组件代码

import React, { useRef, useEffect } from 'react';
import { Row, Col, Table, Container, Button } from 'react-bootstrap';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';

const EcommerceInIndiaPage = ({ generatePDF }) => {
  const contentRef = useRef();
  const chartRef = useRef();

  const ecommercePieChartOptions = {
    chart: {
      type: 'pie',
    },
    title: {
      text: 'E-commerce Market Share in India',
    },
    series: [
      {
        name: 'Categories',
        colorByPoint: true,
        data: [
          { name: 'Electronics', y: 30 },
          { name: 'Fashion', y: 25 },
          { name: 'Grocery', y: 20 },
          { name: 'Home & Furniture', y: 15 },
          { name: 'Others', y: 10 },
        ],
      },
    ],
  };

  const downloadPDF = async () => {
    const pdf = new jsPDF('p', 'mm', 'a4');
    const pageWidth = pdf.internal.pageSize.getWidth();

    // 渲染可选中的文本和表格
    await pdf.html(contentRef.current, {
      x: 10,
      y: 10,
      width: pageWidth - 20,
    });

    // 处理图表为图片插入
    const chartCanvas = await html2canvas(chartRef.current.container);
    const chartImgData = chartCanvas.toDataURL('image/png');
    const chartWidth = pageWidth / 2 - 20;
    const chartHeight = chartCanvas.height * chartWidth / chartCanvas.width;

    pdf.addImage(chartImgData, 'PNG', pageWidth/2 + 10, 30, chartWidth, chartHeight);

    // 添加额外页面
    pdf.addPage();
    pdf.setFontSize(10);
    pdf.text("Conclusion", 10, 10);
    pdf.text("This is a conclusion section with some insights and final thoughts about the E-commerce market trends in India.", 10, 20);

    pdf.addPage();
    pdf.setFontSize(10);
    pdf.text("Content Page", 10, 10);
    pdf.text("Here you can describe the document's structure or provide any additional information.", 10, 20);

    pdf.save('ecommerce-in-india-report.pdf');
  };

  // 保留原有外部调用逻辑(若需要)
  useEffect(() => {
    if (generatePDF && contentRef.current) {
      const htmlContent = contentRef.current.innerHTML;
      generatePDF(htmlContent);
    }
  }, [generatePDF]);

  return (
    <Container className="mt-4">
      <Row>
        <Col ref={contentRef}>
          <h1>E-commerce in India</h1>
          <p>
            E-commerce has experienced tremendous growth in India over the past decade, transforming the way
            people shop and businesses operate. The diverse and dynamic nature of the Indian market has led to
            the rise of various e-commerce segments, catering to a wide range of consumer needs.
          </p>

          <h2>Market Trends</h2>
          <p>
            The Indian e-commerce market is characterized by the dominance of categories such as Electronics,
            Fashion, Grocery, Home & Furniture, and more. According to recent studies, the electronics segment
            holds a significant market share, followed closely by the fashion and grocery sectors.
          </p>

          <h2>Consumer Behavior</h2>
          <p>
            With the advent of affordable smartphones and widespread internet connectivity, more and more
            consumers in India are embracing online shopping. The convenience of browsing through a vast
            assortment of products, coupled with attractive discounts and doorstep delivery, has contributed to
            the popularity of e-commerce.
          </p>

          <h2>E-commerce Market Overview</h2>
          <Table striped bordered hover>
            <thead>
              <tr>
                <th>#</th>
                <th>Category</th>
                <th>Market Share</th>
              </tr>
            </thead>
            <tbody>
              {[
                { category: 'Electronics', marketShare: '30%' },
                { category: 'Fashion', marketShare: '25%' },
                { category: 'Grocery', marketShare: '20%' },
                { category: 'Home & Furniture', marketShare: '15%' },
                { category: 'Others', marketShare: '10%' },
              ].map((item, index) => (
                <tr key={index}>
                  <td>{index + 1}</td>
                  <td>{item.category}</td>
                  <td>{item.marketShare}</td>
                </tr>
              ))}
            </tbody>
          </Table>

          <h3>Challenges and Opportunities</h3>
          <p>
            While the e-commerce sector in India continues to thrive, it faces challenges such as logistical
            complexities and regulatory frameworks. However, the market presents immense opportunities for
            innovation, technological advancements, and the integration of e-commerce into various aspects of
            daily life.
          </p>
        </Col>

        <Col>
          <HighchartsReact 
            highcharts={Highcharts} 
            options={ecommercePieChartOptions} 
            ref={chartRef}
          />
        </Col>
      </Row>
      <Button onClick={downloadPDF}>Download as PDF</Button>
    </Container>
  );
};

export default EcommerceInIndiaPage;

注意事项

  • 样式适配:jsPDF.html()渲染的内容可能和页面样式有差异,需调整CSS确保PDF排版与页面一致,比如字体、间距等。
  • 图表位置:代码中图表坐标为手动计算,需根据实际内容高度调整y值,避免与文本重叠。
  • 分页处理:若文本内容过长,jsPDF.html()会自动分页,需测试确保分页逻辑符合预期。

内容的提问来源于stack exchange,提问作者Sajna Sheeja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 02:57:05