可选择的 PDF 创建功能不适用于 jsPDF

问题描述 投票:0回答:1

尝试从包含文本、表格和图形的 React 组件的 HTML 页面生成 PDF。使用 jsPDF 和 html2canvas 成功创建了 PDF,但面临文本呈现为单个图像的问题,阻碍了单个文本元素的选择。附上生成的 PDF 示例以供参考。

要求在下载 PDF 时能够选择文本内容和表格数据。寻求帮助来确定必要的代码更改以满足此要求。其他包如react-pdf已经尝试过,但没有达到预期的结果。

代码

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


const EcommerceInIndiaPage = ({ generatePDF }) => {
   const componentRef = 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 element = componentRef.current; // Reference to the component
       const canvas = await html2canvas(element);
       const data = canvas.toDataURL('image/png');
       let pdf = new jsPDF('p', 'mm', 'a4');
       let pageWidth = pdf.internal.pageSize.getWidth();
       let pageHeight = pdf.internal.pageSize.getHeight();

       // Calculate the number of pages.
       let imgHeight = canvas.height * pageWidth / canvas.width;
       let heightLeft = imgHeight;

       let position = 0;

       // Add content to the first page.
       pdf.addImage(data, 'PNG', 0, position, pageWidth, imgHeight);
       heightLeft -= pageHeight;

       while (heightLeft >= 0) {
           position = heightLeft - imgHeight;
           pdf.addPage();
           pdf.addImage(data, 'PNG', 0, position, pageWidth, imgHeight);
           heightLeft -= pageHeight;
       }

       // Additional Pages with Dummy Data
       // Adding a new page for conclusion
       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);

       // Adding a content page with dummy data
       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);

       // Save the PDF
       pdf.save('ecommerce-in-india-report.pdf');
   };


   useEffect(() => {
       // Call the generatePDF function with the HTML content when the component mounts
       if (generatePDF && componentRef.current) {
         const htmlContent = componentRef.current.innerHTML;
         generatePDF(htmlContent);
       }
     }, [generatePDF]);

   return (
       <Container className="mt-4" ref={componentRef}>
           <div>
               <Row>
                   <Col>
                       <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>

                       {/* React Bootstrap Table */}
                       <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>
                       {/* Highcharts Pie Chart */}
                       <HighchartsReact highcharts={Highcharts} options={ecommercePieChartOptions} />
                   </Col>
               </Row>
               <Button onClick={downloadPDF}>Download as PDF</Button>
           </div>
       </Container>
   );
};

export default EcommerceInIndiaPage;
reactjs pdf jspdf html-to-pdf
1个回答
0
投票

我能够使用给定 HTML 中的可选文本创建 pdf:

我改变了downloadPdf的功能:

const downloadPDF = async () => {
    const element = componentRef.current; // Reference to the component
    const canvas = await html2canvas(element);
    const data = canvas.toDataURL("image/png");
    let pdf = new jsPDF("p", "mm", "a4");
    let pageWidth = pdf.internal.pageSize.getWidth();
    let pageHeight = pdf.internal.pageSize.getHeight();

    // Calculate the number of pages.
    let imgHeight = (canvas.height * pageWidth) / canvas.width;
    let heightLeft = imgHeight;

    let position = 0;

    // Add content to the first page.
    //    pdf.addImage(data, 'PNG', 0, position, pageWidth, imgHeight);
    //    heightLeft -= pageHeight;

    //    while (heightLeft >= 0) {
    //        position = heightLeft - imgHeight;
    //        pdf.addPage();
    //        pdf.addImage(data, 'PNG', 0, position, pageWidth, imgHeight);
    //        heightLeft -= pageHeight;
    //    }


    // New code
    await pdf.html(element, {
        margin: [20, 20, 20, 20],
        autoPaging: "text",
        width: 170,
        windowWidth: element.offsetWidth,
    });
    const chartCanvas = await html2canvas(chartRef.current);
    pdf.addImage(
        chartCanvas,
        "PNG",
        110,
        20,
        chartCanvas.width / 7,
        chartCanvas.height / 7
    );

    // Additional Pages with Dummy Data
    // Adding a new page for conclusion
    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
    );

    // Adding a content page with dummy data
    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
    );

    // Save the PDF
    pdf.save("ecommerce-in-india-report.pdf");
};

我使用了 .html 方法,它添加了可选择的文本,而不是图像中的文本。不幸的是,jsPDF 在添加 svg 文件时遇到一些问题,因此我必须调整代码以将 svg 转换为 png,然后添加它。可以有更好、更方便的方法来做到这一点。我想提一下,我将chartCanvas的宽度和高度除以7,因为这是chartCanvas宽度与pdf页面宽度的一半之间的比率。这可以用公式代替。另外,我还添加了一个名为 ChartRef 的引用,并将其添加到保存图表的 Col 元素中。我想提一下,我在 repo 中添加了带有大量 CSS 的代码,因为文本可能看起来不太好。如果有一些特定的字体,它们也必须添加到jsPDF中。

© www.soinside.com 2019 - 2024. All rights reserved.