前端怎么将多张图片插入到pdf?

前端怎么将多张图片插入到pdf?

我现在有一个数组,里面放的是图片的base64编码,想通过jspdf这个插件把这些图片生成一个pdf,但是现在遇到的问题就是,两张图片就要占一页,如果有三张图片的话,就需要调用addPage方法,增加一页pdf,把第三张图片插入,但是如果有很多图片的话,就不知道何时去调用addPage方法。
这个是我目前搜到的教程,希望有人给出答案。

<template>
  <div>
    <video ref="video" autoplay width="400" height="300">video>
        <button @click="btnTakePhotoClicked()">Take photobutton>
        <canvas ref="canvas" width="400" height="300">canvas>
        <a href="" download="canvas.jpeg" id="save_herf">
            <img src="" id="save_img" alt="">
        a>
    <button @click="addpage">增页button>
    <button @click="inserImg">图片插入button>
    <button @click="getSize">获取图片高度button>
    <button @click="savePDF">保存button>
  div>
template>

<script>
import {jsPDF} from 'jspdf';
const recordPdf = new jsPDF('p', 'px')
export default {
  data() {
    return {
      imgList: [],
      currentW: 1,
      currentH: 1,
      currentImg: ""
    }
  },
  mounted(){
        this._initVueApp();
        this.btnTakePhotoClicked();
    },
    
    methods:{
        async _initVueApp(){
            this.$refs.video.srcObject= await navigator.mediaDevices.getUserMedia({video:true,audio:false});            
            this._context2d=this.$refs.canvas.getContext("2d");
            this.canvas=this.$refs.canvas;
        },
        
        btnTakePhotoClicked(){
            this._context2d.drawImage(this.$refs.video,0,0,400,300)
            var img = document.createElement("img"); // 创建img元素
            img.src =this.canvas.toDataURL("image/png"); // 截取视频第一帧
            var svaeHref = document.getElementById("save_herf");
            console.log(img.src)
            this.imgList.push(img.src)
      this.currentImg = img.src
            var sd=document.getElementById("save_img");
            svaeHref.href = img.src;
            sd.src=img.src
        },
    addpage() {
      recordPdf.addPage()
    },
    async inserImg() {
      for(let url of this.imgList) {
        let { width, height } = await this.getImgWidthHeight(url)
        recordPdf.addImage(url, 'png', 1, this.currentH, width, height)
        this.currentH = height
        this.currentW = width
      }
      // recordPdf.addImage(this.currentImg, 'png', 1, 1)
      // this.saveToPDF()
    },
    savePDF() {
      recordPdf.save("PDF存档.pdf")
    },
    async getSize() {
      const { width, height } = await this.getImgWidthHeight(this.currentImg)
      console.log(width);
      console.log(height);
    },
    async saveToPDF() {
      // 生成pdf
      // 第一个参数:l横向,p纵向
      // 第二个参数:计量单位: cm mm px等
      // 第三个参数:格式: 默认a4
      // this.saveLoading = false
      // const { maxWidth, maxHeight } = await this.getAllHeight()
      const recordPdf = new jsPDF('p', 'px')
      // 从top的位置开始加图片
      for (let i = 0; i < this.imgList.length; i++) {
        const { url } = this.imgList[i]
        const { width, height } = await this.getImgWidthHeight(url)
        recordPdf.addImage(url, 'png', 1, 1, width, height)
        recordPdf.addPage()
      }
      // 删除最后一页留白
      // const targetPage = recordPdf.internal.getNumberOfPages()
      // recordPdf.deletePage(targetPage)
      recordPdf.save('PDF存档.pdf')
    },
    // 获取图片数组里面最大的宽度和高度
    async getMaxWidthHeight() {
      const widthList = []
      const heightList = []
      let maxHeight = 0
      let maxWidth = 0
      for (let i = 0; i < this.imgList.length; i++) {
        const { url } = this.imgList[i]
        const { width, height } = await this.getImgWidthHeight(url)
        widthList.push(width)
        heightList.push(height)
      }
      // 把数组变成升序然后倒过来取第一个就是拿最大宽度
      maxWidth = widthList.sort().reverse()[0]
      maxHeight = heightList.sort().reverse()[0]
      return {
        maxWidth,
        maxHeight,
      }
    },
    //获取图片宽高
    getImgWidthHeight(src) {
      return new Promise((resolve, reject) => {
        const img = new Image()
        img.src = src
        // 图片是否有缓存 如果有缓存可以直接拿 如果没有缓存 需要从onload拿
        if (img.complete) {
          const { width, height } = img
          resolve({
            width,
            height,
          })
        } else {
          img.onload = function () {
            const { width, height } = img
            resolve({
              width,
              height,
            })
          }
        }
      })
    },
    }
}
script>

https://www.jianshu.com/p/43d69b8ff8e8

如果可以,也可以上传到后台去处理。

基于new Bing的回答:
你可以在遍历图片数组时,检查当前页面已经插入的图片数量,如果达到了每页图片数量的上限,就调用addPage()方法增加一页pdf,然后把新的图片插入到新的一页上。你可以定义一个变量来记录每页应该插入的图片数量,比如说:

const IMAGES_PER_PAGE = 2; // 每页插入两张图片
const doc = new jsPDF();

let imageCount = 0; // 当前页面已经插入的图片数量

imageArray.forEach(image => {
  // 插入图片到pdf
  doc.addImage(image, 'JPEG', x, y, width, height);

  // 更新图片数量
  imageCount++;

  // 如果当前页面已经插入了足够数量的图片,就增加一页pdf
  if (imageCount === IMAGES_PER_PAGE) {
    doc.addPage();
    imageCount = 0; // 重置图片数量
  }
});

// 保存pdf文件
doc.save('my_images.pdf');


这段代码会在每插入两张图片时自动增加一页pdf。你可以根据需要修改IMAGES_PER_PAGE变量来调整每页图片数量。

先计算出每页能容纳的图片数量,然后根据这个数量动态地添加新页

<template>
  <div>
    <button @click="addImage">添加图片</button>
    <button @click="savePDF">保存为 PDF</button>
  </div>
</template>

<script>
import { jsPDF } from 'jspdf';

export default {
  data() {
    return {
      images: [],
      maxImagesPerPage: 2,
    };
  },
  methods: {
    async addImage() {
      const image = await this.getImage(); // 获取图片
      this.images.push(image); // 添加到图片数组
    },
    async getImage() {
      const canvas = document.createElement('canvas');
      const context = canvas.getContext('2d');
      const img = new Image();
      img.src = 'data:image/png;base64,<image_base64>';
      await new Promise((resolve) => img.onload = resolve);
      canvas.width = img.width;
      canvas.height = img.height;
      context.drawImage(img, 0, 0);
      return canvas.toDataURL('image/jpeg', 0.8);
    },
    async savePDF() {
      const doc = new jsPDF();

      let pageIndex = 1;
      let imageIndex = 0;
      let x = 10;
      let y = 10;
      const maxPerPage = this.maxImagesPerPage;

      while (imageIndex < this.images.length) {
        const images = this.images.slice(imageIndex, imageIndex + maxPerPage);

        for (let i = 0; i < images.length; i++) {
          const image = images[i];
          const img = await this.loadImage(image);
          const width = doc.internal.pageSize.width / maxPerPage - 20;
          const height = (img.height * width) / img.width;

          doc.addImage(image, 'JPEG', x, y, width, height);
          x += width + 10;
        }

        // 增加一页
        doc.addPage();
        pageIndex++;
        x = 10;
        y = 10;

        imageIndex += maxPerPage;
      }

      doc.deletePage(pageIndex); // 删除最后一页,因为它是空的

      doc.save('images.pdf');
    },
    loadImage(url) {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = reject;
        img.src = url;
      });
    },
  },
};
</script>

以下内容部分参考ChatGPT模型:


可以通过设置每一页的图片数量来解决这个问题,比如每一页最多放两张图片,当添加第三张图片时,就调用addPage方法增加一页。具体实现可以参考以下代码:

async inserImg() {
  let count = 0
  for(let url of this.imgList) {
    let { width, height } = await this.getImgWidthHeight(url)
    recordPdf.addImage(url, 'png', 1, this.currentH, width, height)
    this.currentH += height
    count++
    if (count % 2 === 0) {
      recordPdf.addPage()
      this.currentH = 1
    }
  }
}

在这段代码中,我们设置了一个count变量来记录当前页已经插入了多少张图片,当count为2的倍数时就调用addPage方法增加一页,并把currentH设置为1,从新一页的顶部开始插入图片。这样就可以保证每一页最多只有两张图片了。


如果我的建议对您有帮助、请点击采纳、祝您生活愉快

首先,我们需要将所有的图片插入到 PDF 中,同时保证每两张图片占用一页,也就是说,每当我们插入一张图片时,需要判断当前页是否还有剩余空间,如果没有,就调用 addPage() 方法增加一页,然后将图片插入到新页中。因此,我们需要一个计算当前页剩余空间的函数,代码如下:

function getAvailableSpaceOnPage(doc) {
  const totalPages = doc.getNumberOfPages();
  const currentPage = doc.internal.getCurrentPageInfo().pageNumber;
  const pageHeight = doc.internal.pageSize.height;
  const y = currentPage === 1 ? 0 : doc.internal.pageSize.height;
  const availableHeight = pageHeight - (y + doc.internal.getVerticalCoordinateString(doc.internal.pageSize.height));
  return availableHeight;
}

接下来,我们需要一个循环来遍历所有图片,将它们插入到 PDF 中。对于每一张图片,我们需要计算它的宽度和高度,并根据当前页剩余空间的大小,判断是否需要调用 addPage() 方法。代码如下:

async function insertImages(doc, imageUrls) {
  for (let i = 0; i < imageUrls.length; i++) {
    const imageUrl = imageUrls[i];
    const { width, height } = await getImageSize(imageUrl);
    const availableHeight = getAvailableSpaceOnPage(doc);
    if (height > availableHeight) {
      doc.addPage();
    }
    doc.addImage(imageUrl, 'JPEG', 0, 0, width, height);
  }
}


其中,getImageSize() 函数用于获取图片的宽度和高度,具体实现可以参考这个问题的另一个回答。

最后,我们可以在 Vue 组件中调用以上两个函数,将所有图片插入到 PDF 中,并保存 PDF 文件,代码如下:

import { jsPDF } from 'jspdf';

export default {
  data() {
    return {
      imageUrls: [], // 图片的 URL 数组
    };
  },
  methods: {
    async generatePDF() {
      const doc = new jsPDF('p', 'pt', 'a4');
      await insertImages(doc, this.imageUrls);
      doc.save('images.pdf');
    },
  },
};


这样,我们就可以将多张图片插入到 PDF 中了。希望这个解答能够帮助到你!

该回答参考ChatGPT:
可以通过循环遍历数组中的每张图片,然后在每一次循环中先判断当前页面已经插入了多少张图片,如果数量已经到达一页上限,则调用addPage方法添加新的一页,接着再将当前图片插入到pdf中即可。具体代码示例如下:

var doc = new jsPDF();
var imgDataArray = ["base64_1", "base64_2", "base64_3", ...];

var imgWidth = 210; // 图片宽度
var pageHeight = 295; // 页面高度
var imgHeight = imgWidth / doc.internal.pageSize.width * doc.internal.pageSize.height; // 图片高度

var currentPage = 1;
var maxImgPerPage = Math.floor(pageHeight / imgHeight);

for (var i = 0; i < imgDataArray.length; i++) {
  if (i % maxImgPerPage === 0) {
    doc.addPage();
    currentPage++;
  }
  doc.addImage(imgDataArray[i], 'JPEG', 0, (i % maxImgPerPage) * imgHeight, imgWidth, imgHeight);
}

doc.save('images.pdf');

其中,imgWidth为图片宽度,pageHeight为页面高度,imgHeight根据图片宽度和页面高度计算得到,currentPage保存当前页数,maxImgPerPage保存每页最多能够插入的图片数量。在循环中,先判断当前页数已经插入的图片数量是否达到了一页上限,如果是则调用addPage方法添加新的一页,同时更新当前页数,然后将当前图片插入到pdf中。最后调用save方法将生成的pdf保存到本地。


```javascript
<!DOCTYPE html>
<html>
<head>
  <title>Insert multiple images to PDF using jsPDF</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.3.1/jspdf.umd.min.js"></script>
</head>
<body>
  <div id="pdfContainer"></div>

  <script>
    // 用于保存图片的URL数组
    const imageURLs = [
      'https://example.com/image1.png',
      'https://example.com/image2.png',
      'https://example.com/image3.png',
    ];

    // 创建一个新的PDF文档
    const doc = new jsPDF();

    // 将所有图片插入到PDF中
    Promise.all(imageURLs.map(url => fetch(url)))
      .then(responses => Promise.all(responses.map(res => res.blob())))
      .then(blobs => {
        blobs.forEach((blob, i) => {
          const reader = new FileReader();
          reader.onload = () => {
            doc.addImage(reader.result, 'PNG', 10, 10 + i * 50, 50, 50);
            if (i === blobs.length - 1) {
              doc.save('images.pdf'); // 将PDF保存到本地
            }
          };
          reader.readAsDataURL(blob);
        });
      });
  </script>
</body>
</html>


```

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先,在添加图片时,我们需要知道当前页面的高度,以便选择新建页面或将图片插入到当前页面。因此,我们可以创建一个变量 currentPageHeight 来记录当前页面的高度,并在插入图片后更新它。

同时,我们需要知道当前图片的高度以便将其插入到合适的位置。因此,我们可以在插入图片前使用 getImageHeight() 方法获取当前图片的高度。

基于此,以下是实现该功能的代码:

<template>
  <div>
    <!-- ... -->

    <button @click="insertImages">插入图片到PDF</button>
    <button @click="savePDF">保存PDF</button>
  </div>
</template>

<script>
import jsPDF from 'jspdf'

export default {
  data() {
    return {
      imgList: [], // 图片 base64 编码列表
      currentPageHeight: 0, // 当前页的高度
    }
  },
  methods: {
    // 获取图片高度
    async getImageHeight(src) {
      const img = new Image()
      img.src = src
      await img.decode() // 等待图片加载完成
      return (img.height * 72) / img.yDPI * 1.33333 // 像素转单位(以 PDF 为例,1像素=0.75pt)
    },

    // 将图片列表插入到 PDF 中
    async insertImages() {
      const pdf = new jsPDF('p', 'pt', 'a4')

      for (let i = 0; i < this.imgList.length; i++) {
        const imgUrl = this.imgList[i]
        const imgHeight = await this.getImageHeight(imgUrl)

        if (this.currentPageHeight + imgHeight > pdf.internal.pageSize.height) {
          // 插入图片会超出当前页,需要新建一页
          pdf.addPage()
          this.currentPageHeight = 0
        }

        pdf.addImage(imgUrl, 'JPEG', 0, this.currentPageHeight, pdf.internal.pageSize.width, imgHeight)

        this.currentPageHeight += imgHeight
      }

      // 下载PDF
      pdf.save('test.pdf')
    },

    // 将 canvas 保存为图片
    saveAsImage(canvas) {
      canvas.toBlob((blob) => {
        const imageUrl = URL.createObjectURL(blob)
        this.imgList.push(imageUrl)
      }, 'image/jpeg', 0.95)
    },

    // 拍照按钮点击事件
    async btnTakePhotoClicked() {
      // ...拍照并将截图保存到 canvas...

      this.saveAsImage(this.canvas)
    },

    savePDF() {
      this.insertImages()
    },
  },
}
</script>

说明:

  1. getImageHeight() 方法中,我们创建了一个 Image 对象来获取图片信息。使用 await img.decode() 等待图片信息获取完成,因为在调用该方法前,图片可能没有加载完成,如果没有完成可能会导致获取的高度不准确。

  2. insertImages() 方法中,我们在插入图片之前使用 this.currentPageHeight 变量检查当前页是否有足够的空间插入图片。如果没有,则新建一页。

  3. 使用 pdf.addImage() 方法将图片插入 PDF。将其 xy 坐标设置为 0 和当前页面的高度,以便将其放在当前页的最底部。

  4. saveAsImage() 方法中我们将 canvas 转换为图片,并将其 base64 编码保存到 imgList 中。

  5. savePDF() 方法将 imgList 中的图片插入到 PDF 中并进行下载。

希望这个解答能够帮助到您!
如果我的回答解决了您的问题,请采纳!

引用chatGPT作答,你可以使用addImage方法将base64编码的图片插入到pdf中。对于每个图片,你可以在插入前获取其高度和宽度,然后将其添加到pdf中,如果添加此图像会导致超出页面边界,则调用addPage方法添加新页面,并在新页面上添加图像。这里是一个基本示例:

import { jsPDF } from 'jspdf'

// 创建新的PDF文档
const doc = new jsPDF()

// 图像列表
const images = ['image1.png', 'image2.png', 'image3.png']

// 逐个添加图像
for (const img of images) {
  // 加载图像
  const image = await loadImage(img)

  // 获取图像大小
  const width = image.width
  const height = image.height

  // 如果当前页无法容纳该图像,则添加新页
  if (doc.getHeight() < height) {
    doc.addPage()
  }

  // 将图像添加到当前页
  doc.addImage(image.src, 'PNG', 10, 10, width, height)
}

// 保存PDF
doc.save('images.pdf')

// 加载图像
function loadImage(url) {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = () => resolve(img)
    img.onerror = reject
    img.src = url
  })
}

这个示例加载图像并逐个将它们添加到PDF中。如果当前页无法容纳图像,则添加新页。最后,整个PDF将被保存为文件。要让它适应你的用例,你需要从images数组中替换图像,并调整x和y坐标以控制图像的位置和间距。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

如何将多个图片合成一个pdf
可以借鉴下
https://blog.csdn.net/qq_33537961/article/details/124959386