从零开始构建PDF阅读器

便携文档格式(PDF)被广泛用于在各种平台上共享文档。PDF之所以受欢迎,是因为它以一种方式保持文档的格式和布局,使得任何操作系统或PDF查看器都不会显示任何修改的迹象。PDF是通过称为PDF查看器的软件工具来显示的,这些工具具有许多与文档交互的功能,如导航、放大和缩小以及跳转到特定页面。

每个PDF查看器都有特定的功能,这限制了新功能的可能性。因此,开发人员可能希望创建自己的PDF查看器软件,以满足其特定的需求和偏好,如文档分析或数据提取。创建自定义PDF查看器有许多优势,其中一些如下:

在本文中,您将使用PDF.js库构建一个简单的自定义PDF查看器。PDF.js是Mozilla开发的基于HTML5的开源PDF查看器库,用于呈现和解析PDF。

使用PDF.js库开发PDF查看器

在开始之前,您需要选择一个代码编辑器和PDF.js库,可以通过CDN(本教程中使用)连接或从GitHub下载。

设置环境

首先,您将设置一个Vanilla JS项目,其中包含一个简单的包含HTML、CSS和JavaScript功能的网页。

在文件夹中设置一个名为PDF Viewer 的项目文件夹,并在文件夹中创建以下三个文件:

  1. index.html
  2. styles.css
  3. viewer.js

项目文件夹结构应如下所示:

项目结构

为PDF查看器创建用户界面

下一步是创建一个界面来使用PDF查看器。

打开index.html文件,然后输入以下代码并保存:







  

  

  Simple PDF Viewer

  





  

Simple PDF Viewer

Page 1

上述代码创建了一个简单的界面,包括以下元素:

除了创建用户界面外,还有两个用于外部JavaScript文件的脚本标签,用于向网页添加功能。

第一个脚本标签https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js是用于呈现PDF文档的PDF.js库的链接。这将把PDF.js库集成到您的项目中。

第二个脚本标签viewer.js是用于实现PDF查看器功能的自定义JavaScript文件的链接。

这样,HTML文件中的代码就结束了。生成的网页应如下所示:

PDF查看器

使用CSS为界面添加样式

虽然本教程不侧重于为用户界面添加样式,但您可以使其看起来更加美观。将以下代码保存在styles.css中:

/* styles.css */

body {

    display: flex;

    flex-direction: column;

    align-items: center;

    justify-content: center;

    height: 100vh;

    margin: 0;

    font-family: Arial, sans-serif;

  }



  #pdf-container {

    border: 1px solid #ccc;

    overflow: auto;

    width: 80%;

    max-width: 800px;

    height: 70vh;

  }



  .button-group, #zoom-controls, #file-controls {

    display: flex;

    align-items: center;

    margin-top: 10px;

  }



  .button-group button, #zoom-controls button, #file-controls button, #file-controls input[type="file"] {

    margin: 0 5px;

    padding: 5px 10px;

    border: none;

    background-color: #007bff;

    color: #fff;

    cursor: pointer;

    border-radius: 4px;

    font-size: 14px;

    transition: background-color 0.3s ease;

  }



  .button-group button:hover, #zoom-controls button:hover, #file-controls button:hover, #file-controls input[type="file"]:hover {

    background-color: #0056b3;

  }



  #go-to-page-input, #go-to-page-btn {

    margin-left: 5px;

  }

上述代码将元素居中,为显示PDF的空间进行了组织,并对所有按钮和输入字段进行了对齐。

生成的网页现在应如下所示:

带有CSS样式的PDF查看器

使用JavaScript和PDF.js添加功能

现在,您已经使用CSS组织了PDF查看器的界面。最后一步是使用JavaScript和PDF.js库添加功能。

首先,为了向PDF查看器添加功能,您需要将所有相关代码放入名为DOMContentLoaded的事件监听器中。这样可以确保在HTML文档完全加载后执行JavaScript代码:

document.addEventListener('DOMContentLoaded', function() {

    // 所有代码在此处

});

您还需要通过JavaScript启用与HTML(DOM)元素的交互,例如按钮和输入字段。document.getElementById()函数允许访问文档对象模型(DOM)元素,从而可以为稍后使用的每个元素创建变量:

const pdfContainer = document.getElementById('pdf-container');

const prevPageBtn = document.getElementById('prev-page');

const nextPageBtn = document.getElementById('next-page');

const pageNumSpan = document.getElementById('page-num');

const goToPageInput = document.getElementById('go-to-page-input'); 

const goToPageBtn = document.getElementById('go-to-page-btn'); 

const zoomOutBtn = document.getElementById('zoom-out');

const zoomInBtn = document.getElementById('zoom-in');

const fileInput = document.getElementById('file-input');

然后,您将初始化以下三个变量:pdfDocpageNumscalepdfDoc变量存储加载的PDF文档实例,pageNum变量跟踪当前显示的页面编号,scale变量用于跟踪缩放比例,以实现放大和缩小功能:

let pdfDoc = null;

let pageNum = 1;

let scale = 1.0;

接下来,renderPage()函数呈现加载的PDF文件的特定页面。它获取PDF页面,调整画布尺寸以匹配页面,清除容器,并将页面内容呈现到画布上,从而在容器内有效地显示页面:

async function renderPage(num) {
  const page = await pdfDoc.getPage(num);

  const viewport = page.getViewport({ scale: scale });

  const canvas = document.createElement('canvas');

  const canvasContext = canvas.getContext('2d');


  canvas.height = viewport.height;

  canvas.width = viewport.width;

  pdfContainer.innerHTML = '';

  pdfContainer.appendChild(canvas);

  const renderContext = {

    canvasContext,

    viewport,

  };

  await page.render(renderContext);
}

loadPDF()函数从给定的URL加载PDF文档,使用pdfjsLib.getDocument()方法。然后调用renderPage()来显示初始页面并更新页面计数:

async function loadPDF(url) {
  const loadingTask = pdfjsLib.getDocument(url);

  pdfDoc = await loadingTask.promise;

  renderPage(pageNum);

  pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;
}

接下来,您将为多个按钮添加事件监听器,以实现点击功能,例如:

prevPageBtn.addEventListener('click', () => {

  if (pageNum > 1) {

    pageNum--;

    renderPage(pageNum);

    pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;

  }

});



nextPageBtn.addEventListener('click', () => {

  if (pageNum < pdfDoc.numPages) {

    pageNum++;

    renderPage(pageNum);

    pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;

  }

});



goToPageBtn.addEventListener('click', () => { // 用于“跳转到页面”按钮的事件监听器

  const targetPage = parseInt(goToPageInput.value);

  if (targetPage >= 1 && targetPage <= pdfDoc.numPages) {

    pageNum = targetPage;

    renderPage(pageNum);

    pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;

  }

});



zoomOutBtn.addEventListener('click', () => {

  if (scale > 0.25) {

    scale -= 0.25;

    renderPage(pageNum);

  }

});



zoomInBtn.addEventListener('click', () => {

  if (scale < 3) {

    scale += 0.25;

    renderPage(pageNum);

  }

});

最后一部分是fileInput监听器,用于检查change事件以加载和呈现用户从本地文件资源管理器中选择的任何文件:

fileInput.addEventListener('change', async (event) => {

  const selectedFile = event.target.files[0];

  if (selectedFile) {

    const fileURL = URL.createObjectURL(selectedFile);

    loadPDF(fileURL);

  }
});

以下是添加功能的完整代码。打开已创建的viewer.js文件,然后输入以下代码并保存:

document.addEventListener('DOMContentLoaded', function() {

    const pdfContainer = document.getElementById('pdf-container');

    const prevPageBtn = document.getElementById('prev-page');

    const nextPageBtn = document.getElementById('next-page');

    const pageNumSpan = document.getElementById('page-num');

    const goToPageInput = document.getElementById('go-to-page-input'); // 添加的输入元素

    const goToPageBtn = document.getElementById('go-to-page-btn'); // 添加的按钮元素

    const zoomOutBtn = document.getElementById('zoom-out');

    const zoomInBtn = document.getElementById('zoom-in');

    const fileInput = document.getElementById('file-input');



    let pdfDoc = null;

    let pageNum = 1;

    let scale = 1.0;



    async function renderPage(num) {

      const page = await pdfDoc.getPage(num);

      const viewport = page.getViewport({ scale: scale });



      const canvas = document.createElement('canvas');

      const canvasContext = canvas.getContext('2d');



      canvas.height = viewport.height;

      canvas.width = viewport.width;

      pdfContainer.innerHTML = '';

      pdfContainer.appendChild(canvas);



      const renderContext = {

        canvasContext,

        viewport,

      };

      await page.render(renderContext);

    }



    async function loadPDF(url) {

      const loadingTask = pdfjsLib.getDocument(url);

      pdfDoc = await loadingTask.promise;

      renderPage(pageNum);

      pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;

    }



    prevPageBtn.addEventListener('click', () => {

      if (pageNum > 1) {

        pageNum--;

        renderPage(pageNum);

        pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;

      }

    });



    nextPageBtn.addEventListener('click', () => {

      if (pageNum < pdfDoc.numPages) {

        pageNum++;

        renderPage(pageNum);

        pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;

      }

    });



    goToPageBtn.addEventListener('click', () => { // 用于“跳转到页面”按钮的事件监听器

      const targetPage = parseInt(goToPageInput.value);

      if (targetPage >= 1 && targetPage <= pdfDoc.numPages) {

        pageNum = targetPage;

        renderPage(pageNum);

        pageNumSpan.textContent = `Page ${pageNum} of ${pdfDoc.numPages}`;

      }

    });



    zoomOutBtn.addEventListener('click', () => {

      if (scale > 0.25) {

        scale -= 0.25;

        renderPage(pageNum);

      }

    });



    zoomInBtn.addEventListener('click', () => {

      if (scale < 3) {

        scale += 0.25;

        renderPage(pageNum);

      }

    });



    fileInput.addEventListener('change', async (event) => {

      const selectedFile = event.target.files[0];

      if (selectedFile) {

        const fileURL = URL.createObjectURL(selectedFile);

        loadPDF(fileURL);

      }

    });

});

这标志着使用PDF.js开发自定义PDF查看器的开发工作已经完成。

测试PDF查看器

使用PDF.js完成PDF查看器项目后,现在让我们尝试渲染一些PDF并看看它的效果。

如果你渲染一个PDF文件,它会看起来像这样:

PDF查看器测试

放大:

PDF查看器:放大

缩小:

PDF查看器:缩小

下一页:

PDF查看器:下一页

上一页:

PDF查看器:上一页

结论

在本文中,你探索了如何使用PDF.js库从头开始开发自定义PDF查看器。你可以在这些步骤的基础上构建许多不同版本的PDF查看器,添加你需要的任何功能。

你可以在这个GitHub存储库中找到本文中使用的所有代码。

展开阅读全文

页面更新:2024-04-22

标签:字段   阅读器   变量   按钮   元素   页面   代码   功能   文档   文件   项目

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top