情景

当前在做一个简历模板,有使用到网页打印转为 PDF 文件的功能。PDF 是转成功了,但是页码功能却很麻烦,以下是几种可以生成页面的方式。

1. 页面打印勾选

最简单的就是在打印时勾选页眉和页脚了。

但是这种方式会在页脚左侧显示当前网址,页眉显示生成时间和标题,一般简历 pdf 都不会带上这些东西的,带上这些别人可能会以为你不够专业。

2. 使用 css 中的 @page

@page 会在打印时生效,它的子选择器可以是@top-right @bottom-right等,配合 content 属性以及自增属性可以做到打印时生成页码,也就是它可以在 pdf 内容四周的白边上带上页码。

@page {
  // 在页面右下角生成页码
   @bottom-right {
      content: counter(page) " of " counter(pages);
   }
}

这东西看上去好像挺好的,但是有个天大的缺陷就是该功能只是昙花一现,目前已没有任何浏览器为它实现该功能。

3. 使用 pdf-lib

使用 pdf-lib可以读取一个已有的 PDF 文件,然后像添加水印一样为 PDF 文件的每个页面添加一个页码。


import { degrees, PDFDocument, rgb, StandardFonts } from 'pdf-lib';

async function modifyPdf() {
  const url = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
  const existingPdfBytes = await fetch(url).then(res => res.arrayBuffer())

  const pdfDoc = await PDFDocument.load(existingPdfBytes)
  const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica)

  const pages = pdfDoc.getPages()
  const firstPage = pages[0]
  const { width, height } = firstPage.getSize()
  firstPage.drawText('This text was added with JavaScript!', {
    x: 5,
    y: height / 2 + 300,
    size: 50,
    font: helveticaFont,
    color: rgb(0.95, 0.1, 0.1),
    rotate: degrees(-45),
  })

  const pdfBytes = await pdfDoc.save()
}

该方式优点是可在任意 js 环境中使用。
缺点则是需要用浏览器把 PDF 生成出来,然后再次为 PDF 文件生成页码,需要操作两步,除非用代码生成 PDF 才能简化为一步操作。

4. 代码插入

该方式需要固定住打印尺寸,然后计算出每个页面底部位置,然后插入页码,具体见 https://stackoverflow.com/a/64884005/23944718

<html>
    <head>
        <style type="text/css">
            @page {
              size: A4;
              margin: 0; 
            }

            body {
              margin: 0;
            }
        </style>
    </head>
    <body>
        <script type="text/javascript">
          window.onload = addPageNumbers;

          function addPageNumbers() {
            var totalPages = Math.ceil(document.body.scrollHeight / 1123);  //842px A4 pageheight for 72dpi, 1123px A4 pageheight for 96dpi, 
            for (var i = 1; i <= totalPages; i++) {
              var pageNumberDiv = document.createElement("div");
              var pageNumber = document.createTextNode("Page " + i + " of " + totalPages);
              pageNumberDiv.style.position = "absolute";
              pageNumberDiv.style.marginTop = "calc((" + i + " * (297mm - 0.5px)) - 40px)"; //297mm A4 pageheight; 0,5px unknown needed necessary correction value; additional wanted 40px margin from bottom(own element height included)
              pageNumberDiv.style.height = "16px";
              pageNumberDiv.appendChild(pageNumber);
              document.body.insertBefore(pageNumberDiv, document.getElementById("content"));
              pageNumberDiv.style.left = "calc(100% - (" + pageNumberDiv.offsetWidth + "px + 20px))";
            }
          }
        </script>
        <div id="content">
            Lorem ipsum....
        </div>
    </body>
</html>

该方式也是可以的,固定尺寸其实问题也不大,毕竟简历打印都是 A4 大小的。

5. Paged.js

该方式见于 https://stackoverflow.com/a/66688870/23944718 ,我也没试过,但是有人说可以,有人说有问题,先搁这吧。

最后

以上各方法各有优缺点,我目前用的是用网页生成 PDF 文件,用pdf-lib 为 PDF
文件生成页码,其实最优选还是用库生成 PDF文件,这样就能随心所欲想要什么样式就什么样式,但是因为我的是 html 的,用库生成的话挺麻烦的要搞两套样式,所以先就这样了。

评论

0 / 800
全部评论()