搜索
首页web前端js教程Aurelia的冒险:创建自定义PDF查看器

Adventures in Aurelia: Creating a Custom PDF Viewer

本文经Vildan Softic同行评审。感谢所有SitePoint的同行评审员,让SitePoint的内容达到最佳状态!

在Web应用程序中处理PDF文件一直以来都非常棘手。如果幸运的话,你的用户只需要下载文件即可。但有时,用户需要更多功能。过去,我比较幸运,但这次,我们的用户需要应用程序显示PDF文档,以便他们可以保存与每个页面相关的元数据。以前,人们可能使用昂贵的PDF插件(例如Adobe Reader)在浏览器中运行来实现此目的。然而,经过一番时间和实验,我找到了一种更好的方法来在Web应用程序中集成PDF查看器。今天,我们将了解如何使用Aurelia和PDF.js简化PDF处理。

核心要点

  • 利用Aurelia和PDF.js创建一个自定义的、高效的PDF查看器,具有缩放和滚动等功能,增强用户交互和性能。
  • 在Aurelia中实现当前页面和缩放级别等属性的双向数据绑定,允许在应用程序中无缝集成和动态更新。
  • 将PDF查看器开发成可重用的Aurelia自定义元素,可以在应用程序中添加多个查看器而不会发生冲突。
  • 利用PDF.js处理PDF渲染,支持异步操作和Web Worker,以卸载处理并提高UI响应速度。
  • 通过考虑虚拟滚动和其他优化来解决潜在的性能问题,尤其是在有效处理大型文档方面。
  • 探索将自定义PDF查看器转换为Aurelia插件的可能性,使其易于集成到其他项目和应用程序中。

概述:目标

我们今天的目标是在Aurelia中构建一个PDF查看器组件,允许查看器和我们的应用程序之间进行双向数据流。我们有三个主要要求:

  1. 我们希望用户能够加载文档、滚动和放大/缩小,并具有良好的性能。
  2. 我们希望能够将查看器属性(例如当前页面和当前缩放级别)与应用程序中的属性进行双向绑定。
  3. 我们希望此查看器是一个可重用的组件;我们希望能够轻松地在应用程序中同时放置多个查看器,而不会发生冲突。

您可以在我们的GitHub仓库中找到本教程的代码,以及此处完成代码的演示。

介绍PDF.js

PDF.js是一个由Mozilla基金会编写的JavaScript库。它加载PDF文档,解析文件和相关的元数据,并将页面输出渲染到DOM节点(通常是<canvas></canvas>元素)。项目中包含的默认查看器为Chrome和Firefox中的嵌入式PDF查看器提供支持,可以用作独立页面或资源(嵌入在iframe中)。

这确实很酷。这里的问题是,默认查看器虽然有很多功能,但它被设计为一个独立的网页。这意味着,虽然它可以集成到Web应用程序中,但它基本上必须在iframe沙箱内运行。默认查看器设计为通过其查询字符串获取配置输入,但是我们不能在初始加载后轻松更改配置,也不能轻松地从查看器获取信息和事件。为了将其与Aurelia Web应用程序集成——包括事件处理和双向绑定——我们需要创建一个Aurelia自定义组件。

注意:如果您需要关于PDF.js的复习,请查看我们的教程:使用Mozilla的PDF.js在JavaScript中进行自定义PDF渲染

实现

为了实现我们的目标,我们将创建一个Aurelia自定义元素。但是,我们不会将默认查看器放入我们的组件中。相反,我们将创建自己的查看器,它连接到PDF.js核心和查看器库,以便我们可以最大限度地控制我们的可绑定属性和渲染。对于我们的初始概念验证,我们将从Aurelia骨架应用程序开始。

样板代码

正如您从上面的链接中看到的那样,骨架应用程序有很多文件,其中许多文件我们不需要。为了简化操作,我们准备了一个精简版本的骨架,并在其中添加了一些内容:

  • 一个Gulp任务,用于将我们的PDF文件复制到dist文件夹(Aurelia用于捆绑)。
  • PDF.js依赖项已添加到package.json。
  • 在应用程序的根目录中,index.html和index.css已经进行了一些初始样式设置。
  • 我们将要使用的文件的空副本已添加。
  • 文件src/resources/elements/pdf-document.css包含自定义元素的一些CSS样式。

所以让我们启动并运行应用程序。

首先,确保全局安装了gulp和jspm:

npm install -g gulp jspm

然后克隆骨架并进入其中:

git clone git@github.com:sitepoint-editors/aurelia-pdfjs.git -b skeleton
cd aurelia-pdfjs

然后安装必要的依赖项:

npm install
jspm install -y

最后运行gulp watch并导航到http://localhost:9000。如果一切按计划进行,您应该会看到一条欢迎消息。

更多设置

接下来要做的是找到几个PDF文件并将它们放在src/documents中。将它们命名为one.pdf和two.pdf。为了最大限度地测试我们的自定义组件,最好其中一个PDF文件非常长,例如可以在古腾堡计划中找到的《战争与和平》。

将PDF文件放在适当位置后,打开src/app.html和src/app.js(按照约定,App组件是Aurelia应用程序的根组件),并将其中的代码替换为这两个文件的代码:src/app.html和src/app.js。在本教程中,我们将不会讨论这些文件,但代码中有很好的注释。

Gulp将自动检测这些更改,您应该会看到我们的应用程序UI呈现。设置就是这样。现在开始展示……

创建Aurelia自定义元素

我们希望创建一个可以直接用于任何Aurelia视图的组件。由于Aurelia视图只是一个包含在HTML5模板标签中的HTML片段,因此一个示例可能如下所示:

npm install -g gulp jspm

<pdf-document></pdf-document>标签是自定义元素的一个示例。它及其属性(如scale和page)不是HTML的原生属性,但我们可以使用Aurelia自定义元素来创建它。自定义元素易于创建,使用Aurelia的基本构建块:视图和ViewModel。因此,我们将首先搭建我们的ViewModel,命名为pdf-document.js,如下所示:

git clone git@github.com:sitepoint-editors/aurelia-pdfjs.git -b skeleton
cd aurelia-pdfjs

这里要注意的主要内容是@bindable装饰器;通过创建具有配置defaultBindingMode: bindingMode.twoWay的可绑定属性,并通过在我们的ViewModel中创建处理程序方法(urlChanged、pageChanged等),我们可以监控和响应我们放置在自定义元素上的相关属性的更改。这将允许我们简单地通过更改元素上的属性来控制我们的PDF查看器。

然后,我们将创建与我们的ViewModel配对的初始视图。

npm install
jspm install -y

(以下内容与原文基本一致,只是对部分语句进行了细微的调整,以保持流畅性和可读性,并避免重复。)

集成PDF.js

PDF.js分为三个部分:核心库(处理PDF文档的解析和解释)、显示库(在核心层之上构建可用的API)以及Web查看器插件(我们前面提到的预构建网页)。出于我们的目的,我们将通过显示API使用核心库;我们将构建我们自己的查看器。

显示API导出一个名为PDFJS的库对象,它允许我们设置一些配置变量并使用PDFJS.getDocument(url)加载我们的文档。该API是完全异步的——它向Web Worker发送和接收消息,因此它大量依赖于JavaScript Promise。我们将主要使用从PDFJS.getDocument()方法异步返回的PDFDocumentProxy对象和从PDFDocumentProxy.getPage()异步返回的PDFPageProxy对象。

尽管文档有点稀疏,但PDF.js有一些创建基本查看器的示例,这里和这里。我们将以此为基础构建我们的自定义组件。

Web Worker集成

PDF.js使用Web Worker来卸载其渲染任务。由于Web Worker在浏览器环境中的运行方式(它们实际上是沙箱化的),我们被迫使用JavaScript文件的直接文件路径来加载Web Worker,而不是通常的模块加载器。幸运的是,Aurelia提供了一个加载器抽象,因此我们不必引用静态文件路径(当我们捆绑应用程序时,这可能会发生变化)。

如果您正在关注我们版本的仓库,您可能已经安装了pdfjs-dist包,否则,您现在需要这样做(例如,使用jspm jspm install npm:pdfjs-dist@^1.5.391)。然后,我们将使用Aurelia的依赖注入模块注入Aurelia的加载器抽象,并使用加载器在我们的构造函数中加载Web Worker文件,如下所示:

加载页面

PDF.js库处理PDF文档的加载、解析和显示。它具有对部分下载和身份验证的内置支持。我们所要做的就是提供相关文档的URI,PDF.js将返回一个Promise对象,该对象解析为表示PDF文档及其元数据的JavaScript对象。

PDF的加载和显示将由我们的可绑定属性驱动;在这种情况下,它将是url属性。基本上,当URL更改时,自定义元素应该要求PDF.js发出对文件的请求。我们将在urlChanged处理程序中执行此操作,并对我们的构造函数进行一些更改以初始化一些属性,并对我们的detached方法进行一些更改以进行清理。

对于文档的每一页,我们将在DOM中创建一个<canvas></canvas>元素,该元素位于具有固定高度的可滚动容器内。为此,我们将使用Aurelia的基本模板功能,使用一个repeater。因为每个PDF页面都可以有自己的大小和方向,所以我们将根据PDF页面视口设置每个canvas元素的宽度和高度。

渲染页面

现在我们已经加载了页面,我们需要能够将它们渲染到DOM元素。为此,我们将依赖于PDF.js的渲染功能。PDF.js查看器库有一个专门用于渲染页面的异步API;他们的网站上有一个很好的示例,展示了如何创建一个renderContext对象并将其传递给PDF.js渲染方法。我们将这段代码从示例中提取出来,并将其包装在一个render函数中:

实现滚动

为了提供熟悉且无缝的体验,我们的组件应该将页面显示为完全可滚动文档的各个部分。我们可以通过使我们的容器具有具有滚动溢出的固定高度来实现这一点,这可以通过CSS来实现。

为了最大限度地提高大型文档的性能,我们将执行以下几件事。首先,我们将利用Aurelia的TaskQueue来批量更改DOM。其次,我们将跟踪PDF.js已经渲染的页面,这样它就不必重做它已经完成的工作。最后,我们将只在滚动停止后渲染可见页面,方法是使用Aurelia的debounce绑定行为。这是我们在滚动时将运行的方法:

实现缩放

当我们缩放时,我们希望更新当前缩放级别。我们将在scaleChanged属性处理程序中执行此操作。基本上,我们将调整所有canvas元素的大小以反映给定比例的每一页的新视口大小。然后,我们将重新渲染当前视口中显示的内容,重新启动循环。

最终结果

让我们回顾一下我们的目标:

  1. 我们希望用户能够加载文档、滚动和放大/缩小,并具有良好的性能。
  2. 我们希望能够将查看器属性(例如当前页面和当前缩放级别)与应用程序中的属性进行双向绑定。
  3. 我们希望此查看器是一个可重用的组件;我们希望能够轻松地在应用程序中同时放置多个查看器,而不会发生冲突。

最终代码可以在我们的GitHub仓库中找到,以及此处完成代码的演示。虽然仍有改进的空间,但我们已经达到了目标!

(以下内容与原文基本一致,只是对部分语句进行了细微的调整,以保持流畅性和可读性,并避免重复。)

项目后分析和改进

总有改进的空间,进行项目后分析并确定未来迭代中需要解决的领域始终是一个好习惯。以下是一些我想在PDF查看器实现方面进行升级的内容:

创建插件

Aurelia提供了一个插件系统。将这个概念验证转换为Aurelia插件将使其成为任何Aurelia应用程序的即用型资源。Aurelia Github仓库提供了一个插件骨架项目,这将是一个良好的起点。这样,其他人就可以使用此功能,而无需重新构建它!

展望

在Web应用程序中处理PDF文件一直以来都非常棘手。但是,凭借当今可用的资源,我们可以通过组合库及其功能来实现比以往更多的事情。今天,我们已经看到一个基本PDF查看器的示例——一个可以通过自定义功能扩展的查看器,因为我们可以完全控制它。可能性是无限的!你准备好构建一些东西了吗?请在下面的评论中告诉我。

关于Aurelia自定义PDF查看器组件的常见问题解答(FAQ)

(以下内容与原文基本一致,只是对部分语句进行了细微的调整,以保持流畅性和可读性,并避免重复。)

以上是Aurelia的冒险:创建自定义PDF查看器的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
node.js流带打字稿node.js流带打字稿Apr 30, 2025 am 08:22 AM

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python vs. JavaScript:性能和效率注意事项Python vs. JavaScript:性能和效率注意事项Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript的起源:探索其实施语言JavaScript的起源:探索其实施语言Apr 29, 2025 am 12:51 AM

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

幕后:什么语言能力JavaScript?幕后:什么语言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来:趋势和预测Python和JavaScript的未来:趋势和预测Apr 27, 2025 am 12:21 AM

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python vs. JavaScript:开发环境和工具Python vs. JavaScript:开发环境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

JavaScript是用C编写的吗?检查证据JavaScript是用C编写的吗?检查证据Apr 25, 2025 am 12:15 AM

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。

JavaScript的角色:使网络交互和动态JavaScript的角色:使网络交互和动态Apr 24, 2025 am 12:12 AM

JavaScript是现代网站的核心,因为它增强了网页的交互性和动态性。1)它允许在不刷新页面的情况下改变内容,2)通过DOMAPI操作网页,3)支持复杂的交互效果如动画和拖放,4)优化性能和最佳实践提高用户体验。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境