【记录一次pdf-lib绘制小票的需求】

1.需求如下:

绘制如上格式的小票为pdf,再进行打印(帮别人做的哈哈)

第一步:

安装插件:pdf-lib 以及 qrcode

npm install @pdf-lib/pdf-lib qrcode

第二步:

绘制表格:

const drawText = (page: any, text: string, x: number, y: number, font: any, fontSize = 12) => {
  page.drawText(text, {
    x,
    y,
    size: fontSize,
    color: rgb(0, 0, 0),
    font,
  });
};

const drawBox = (page: any, x: number, y: number, boxWidth: number, boxHeight: number) => {
  page.drawRectangle({
    x,
    y,
    width: boxWidth,
    height: boxHeight,
    borderWidth: 1,
    borderColor: rgb(0, 0, 0),
  });
};

创建以上两个方法来绘制文本和表格单元格

定义表格的尺寸:

  const startX = 50;
  const startY = height - 50;
  const rowHeight = 30;
  const boxWidth = 500;
  const boxHeight = rowHeight;
  const labelWidth = 100;
  const valueWidth = boxWidth - labelWidth;

实现绘制逻辑:

const generatePdf = async () => {
  const pdfDoc = await PDFDocument.create();
  const page = pdfDoc.addPage([600, 800]);
  const { width, height } = page.getSize();
  const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
  const fontSize = 12;

  const rows = [
    { label: 'chepaihao', value: '[#CH#]' },
    { label: 'gongyingshang', value: '[#GYSQC#]' },
    { label: 'wuliao', value: '[#MZMC#]' },
    { label: 'yicizhongliang', value: '[#MZ#]', secondLabel: 'ercijingzhong', secondValue: '[#PZ#]' },
    { label: 'jingzhong', value: '[#JZ#]' },
    { label: 'yicishijian', value: '[#ZHONGCSJ#]' },
    { label: 'ercishijian', value: '[#HUIPSJ#]' },
    { label: 'dayinshijian', value: '[#dangqianshijianshiqi#]' },
    { label: 'beizhu', value: '' },
  ];

  const startX = 50;
  const startY = height - 50;
  const rowHeight = 30;
  const boxWidth = 500;
  const boxHeight = rowHeight;
  const labelWidth = 100;
  const valueWidth = boxWidth - labelWidth;

  let currentY = startY;

  // 绘制表头
  drawText(page, '[#DCMC#]', startX + boxWidth / 2 - 20, currentY + 10, font, 16);
  currentY -= rowHeight;

  // Draw the table rows
  rows.forEach((row, index) => {
    drawBox(page, startX, currentY, boxWidth, boxHeight);

    if (row.secondLabel) {
      const firstColumnWidth = labelWidth;
      const remainingWidth = boxWidth - firstColumnWidth;
      const cellWidth = remainingWidth / 3;

      drawText(page, row.label, startX + 10, currentY + 10, font);
      drawText(page, row.value, startX + firstColumnWidth + 10, currentY + 10, font);
      drawText(page, row.secondLabel, startX + firstColumnWidth + cellWidth + 10, currentY + 10, font);
      drawText(page, row.secondValue, startX + firstColumnWidth + cellWidth * 2 + 10, currentY + 10, font);

      // Draw vertical lines for columns
      page.drawLine({
        start: { x: startX + firstColumnWidth, y: currentY },
        end: { x: startX + firstColumnWidth, y: currentY + boxHeight },
        thickness: 1,
        color: rgb(0, 0, 0),
      });
      page.drawLine({
        start: { x: startX + firstColumnWidth + cellWidth, y: currentY },
        end: { x: startX + firstColumnWidth + cellWidth, y: currentY + boxHeight },
        thickness: 1,
        color: rgb(0, 0, 0),
      });
      page.drawLine({
        start: { x: startX + firstColumnWidth + cellWidth * 2, y: currentY },
        end: { x: startX + firstColumnWidth + cellWidth * 2, y: currentY + boxHeight },
        thickness: 1,
        color: rgb(0, 0, 0),
      });
    } else {
      drawText(page, row.label, startX + 10, currentY + 10, font);
      drawText(page, row.value, startX + labelWidth, currentY + 10, font);

      // Draw vertical line between label and value
      page.drawLine({
        start: { x: startX + labelWidth, y: currentY },
        end: { x: startX + labelWidth, y: currentY + boxHeight },
        thickness: 1,
        color: rgb(0, 0, 0),
      });
    }

    currentY -= rowHeight;
  });

  //绘制并插入二维码
  const qrCodeValue = 'https://example.com';
  const qrCodeDataUrl = await QRCode.toDataURL(qrCodeValue);

  const qrImageBytes = await fetch(qrCodeDataUrl).then((res) => res.arrayBuffer());
  const qrImage = await pdfDoc.embedPng(qrImageBytes);

  const qrImageSize = 100;
  page.drawImage(qrImage, {
    x: startX + (boxWidth - qrImageSize) / 2,
    y: currentY - qrImageSize - 10,
    width: qrImageSize,
    height: qrImageSize,
  });

  const pdfBytes = await pdfDoc.save();

  // 下载pdf
  const blob = new Blob([pdfBytes], { type: 'application/pdf' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'output.pdf';
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
};

这里的表格绘制列有点头痛,定好规则,根据每一列的宽度和高度来进行计算

最后添加个按钮看看效果:

<template>
  <div>
    <button @click="generatePdf">生成 PDF</button>
  </div>
</template>

实现效果导出后如下:

大功告成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值