让你的PDF合成后不再失真2-文字合成

前言

如果你还没有看过我之前写的让你的PDF合成后不再失真文章,那么请你一定先看完后再继续阅读。

因为上一篇文章的延伸,在之前文章的基础上,我们扩展了在pdf内合成文字的功能。

文字是真文字,不是一张图片。

同样的,能够保证pdf的流正确(矢量的pdf)

不想看过程的可以直接跳转到代码部分,Ctrl+C Ctrl+V

开始

我们还是使用 pdf-lib 库来实现

第一步:注册字体工具

pdfDoc.registerFontkit(fontkit),这里需要引入 pdf-lib 自带的fontkit工具,

第二步:加载字体,并转换成Buffer结构

javaStript 复制代码
const defaultFontBuffer = await fetch(SIMFANGTTF).then(res =>
    res.arrayBuffer()
)

实际上 pdf-lib 提供了好几种字体的引入方式(后面会介绍),这里我们选择最合适的一种

第三步:将Buffer结构的字体嵌入到pdf中

const helveticaFont = await pdfDoc.embedFont(defaultFontBuffer)

  • 在此文档中嵌入字体。输入数据可以提供多个
  • | 类型 | 描述 |
  • | --------------- | ------------------------------------------------------- |
  • | StandardFonts | pdf-lib自带的标准字体 |
  • | string | 包含字体的 base64 编码字符串(或数据 URI) |
  • | Uint8Array | 字体的原始字节 |
  • | ArrayBuffer | 字体的原始字节 |
js 复制代码
 // font=StandardFonts
 import { StandardFonts } from 'pdf-lib'
 const font1 = await pdfDoc.embedFont(StandardFonts.Helvetica)

 // font=string
 const font2 = await pdfDoc.embedFont('AAEAAAAVAQAABABQRFNJRx/upe...')
 const font3 = await pdfDoc.embedFont('data:font/opentype;base64,AAEAAA...')

 // font=Uint8Array
 import fs from 'fs'
 const font4 = await pdfDoc.embedFont(fs.readFileSync('Ubuntu-R.ttf'))

 // font=ArrayBuffer
 const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf'
 const ubuntuBytes = await fetch(url).then(res => res.arrayBuffer())
 const font5 = await pdfDoc.embedFont(ubuntuBytes)

第四步:在pdf的页面内设置该字体

page.setFont(helveticaFont)

第五步:使用 drawText 方法写入文字

javascript 复制代码
page.drawText(`${el.src}`, {
    x: el.x,
    y: el.y,
    size: 16, // 字体大小
    lineHeight: 16 // 字体行高
  })

第一个参数是文字的内容,第二个参数是文字的配置项

注意:这里有个新手容易犯的错误,pdf渲染文字,并不是我们传啥都能显示的,他是一种编码方式,我们文字传递的是 UTF-8 格式,要从字体库里面匹配到对应的编码后,才能将其文字显示出来

字体库这么大,我们要全部引用?

一般常见的字体库都是很庞大的(30+Mb),因为要涉及到世界各个地区的文字、特殊字符等等。

如果我们全量引入的话,工程打包出来的体积就非常大,这是不可取的

所以这时候我们就得创建一个属于自己的字体库。

创建自己的字体库

推荐使用这个网站来创建

tophix.com/assets/js/f...

首先我们打开一个现成的字体库,然后我们自己新建一个自己的字体库

然后我们找到我们需要的字体,将他复制一份,然后切到我们自己的字体库,粘贴

如此反复之后,最后下载自己的字体库即可,这里我们选择TTF的格式

以上就完成了自建字体库,是不是挺简单的!

代码

是基于上篇文章的代码内增加了字体部分的代码,新增的部分用 // +++++++++++++++注释

js 复制代码
import { PDFDocument } from "pdf-lib"
// +++++++++++++++
import fontkit from '@pdf-lib/fontkit'
import SIMFANGTTF from './SIMFANG.TTF'
// +++++++++++++++
  
const getNewPdf = async (pdfBase64, imagesList = []) => {
  // 创建新的pdf
  const pdfDoc = await PDFDocument.create()
  // +++++++++++++++
  // 加载字体
  pdfDoc.registerFontkit(fontkit)
  const defaultFontBuffer = await fetch(SIMFANGTTF).then(res =>
    res.arrayBuffer()
  )
  const helveticaFont = await pdfDoc.embedFont(defaultFontBuffer)
  // +++++++++++++++
  let page = ""
  // 传入的pdf进行格式转换
  const usConstitutionPdf = await PDFDocument.load(pdfBase64)
  // 获取转换后的每一页数据
  const userPdf = usConstitutionPdf.getPages()
  //   将每一个数据 导入到我们新建的pdf每一页上
  for (let index = 0; index < userPdf.length; index++) {
        
    const [existingPage] = await pdfDoc.copyPages(usConstitutionPdf,[index])
    page = pdfDoc.addPage(existingPage)
    // +++++++++++++++
    page.setFont(helveticaFont)
    // +++++++++++++++
    // 如果有传入图片,则遍历信息,并将他合成到对应的页码上
    const imageSel = imagesList.filter((i) => i.pageIndex === index)
      
    if (imageSel.length > 0) {
      for (let idx = 0; idx < imageSel.length; idx++) {
        const el = imageSel[idx]
        const pngImage = await pdfDoc.embedPng(el.src)
        page.drawImage(pngImage, {
          x: +el.x,
          y: +el.y,
          width: +el.width,
          height: +el.height,
        })
       // +++++++++++++++ 
        page.drawText(`${el.src}`, {
            x: el.x,
            y: el.y,
            size: 16, // 字体大小
            lineHeight: 16 // 字体行高
          })
       // +++++++++++++++
      }
    }
  }
  //   保存pdf
  const pdfBytes = await pdfDoc.save()
  // 将arrayButter 转换成 base64 格式
  function ArrayBufferToBase64(buffer) {
    //第一步,将ArrayBuffer转为二进制字符串
    var binary = ""
    var bytes = new Uint8Array(buffer)
    for (var len = bytes.byteLength, i = 0; i < len; i++) {
      binary += String.fromCharCode(bytes[i])
    }
    //将二进制字符串转为base64字符串
    return window.btoa(binary)
  }

  //   console.log("data:application/pdf;base64," + ArrayBufferToBase64(pdfBytes))
  //   最后将合成的pdf返回
  return "data:application/pdf;base64," + ArrayBufferToBase64(pdfBytes)
}
export default getNewPdf

结束!

相关推荐
待磨的钝刨8 分钟前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫4 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦4 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子5 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享6 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
从兄6 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf7 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨7 小时前
VUE+Vite之环境文件配置及使用环境变量
前端