前言
需求是预览本地的pdf/word/epub格式的文件,但是搜索后发现没有可以直接使用的,格式不同,显示的方式和效果也都略有不同。
最后还是分别实现预览的功能。
- 如果只需要预览pdf/word等格式的话,可以使用的方案:vue-office,支持多种文件(docx、excel、pdf)预览的vue组件库,支持vue2/3。也支持非Vue框架的预览。
- 补充功能:pdf选中文字,epub高亮(我的需求是选中pdf/epub的文字后进行收藏)
实现
pdf预览和选中文字高亮
方案:pdfjs+iframe
因为这样可以使用浏览器自带的pdf阅读器,不需要再自己实现小图预览等功能。
pdf.js实现pdf的预览与下载(vue+springboot+pdf.js) 有demo,比较基础的功能。也是本地引入pdf.js的用法
扩展:web打开在线的pdf文件,禁用打印和下载功能
VUE预览PDF文件并利用pdf.js获取鼠标选中的文字和搜索,在iframe中获取选中文字,监听鼠标事件,右键菜单
直接本地引入pdf.js的方法也可以参考上面这篇文章,写的很详细。
主要参考的还是获取选中文字的部分:
getSelectText(){let _this =this;let iframe = document.getElementsByClassName("pdf-viewer-local")[0];let x ="";let y ="";let _x ="";let _y ="";// iframe 加载完成后执行并将双击事件过滤掉,因为双击事件可能也触发滑选,所以为了不误操作,将其剔除
iframe.onload=function(){// 鼠标点击监听
iframe.contentDocument.addEventListener("mousedown",function(e){
x = e.pageX;
y = e.pageY;
_this.isShowNotePop =false;},true);// 鼠标抬起监听
iframe.contentDocument.addEventListener("mouseup",function(e){
_x = e.pageX;
_y = e.pageY;if(x == _x && y == _y)return;//判断点击和抬起的位置,如果相同,则视为没有滑选,不支持双击选中var selection = iframe.contentWindow.getSelection();var range = selection.getRangeAt(0);var choose = selection.toString();
_this.selectText = choose;
console.log("选中文本:"+ choose);},true);};},
扩展:在iframe中获取选中的数据/iframe中鼠标事件 来自上一篇参考文章的参考文章。
docx
Mammoth
旨在转换 .docx 文档(例如由 Microsoft Word 创建的文档),并将其转换为 HTML。 不支持样式。
Vue Word预览之mammoth.js
docx-preview
我的博客:关于实现
epub
功能:实现预览、电子书切换、目录、换背景色、字体大小调整、进度的功能。
方案:使用epub.js,官方文档
版本选择:使用epub对电子书进行渲染(Blocked script execution in 'http://localhost:8080/’ because the document 's frame is sandboxed and the ‘allow-scripts’ permission is not set.),出现了上述报错,原因是epub.js版本太高,所以切换了版本。省流:版本是
[email protected]
参考文章:
- epub.js制作电子书阅读网站 有demo,有源码。不过功能还存在一些问题(比如电子书切换之类的有bug)。 注释还是比较详细的。可以体验参考
- 基于Vue创建的epub小说阅读器效果展示及源码分享 主要是在这篇文章内容上进行移植二改。因为提供了源码。功能也比较全。
- epub.js 踩坑与实践指南阅读后可以对epub.js有一个大概了解,方便二次开发。二次开发的记录 ps.其实这个获取的页数不太准确。但是也没别的方法,怪不得上面的代码用的是百分比进度
- 获取总页数:
this.book.ready
.then(()=>{this.navigation =this.book.navigation;returnthis.book.locations.generate();}).then((result)=>{this.locations =this.book.locations;this.bookAvailable =true;// 获取总页数this.totalPages =this.locations.length();// console.log("Total pages: " + this.totalPages);});
2.左右翻页或跳转页数
通过父子组件间通信传递当前的页码、监听左右翻页或输入页码跳转。
//epub翻页prevPage(){if(this.rendition){
console.log("prev");this.rendition.prev();this.currentPage--;// 向前翻页时更新 currentPage}},nextPage(){if(this.rendition){try{this.rendition.next();this.currentPage++;// 向后翻页时更新 currentPage}catch(error){
console.log("EPUB 下一页出错:", error);alert("出错,请重试或检查 EPUB 文件格式。");}}},
注意:“跳转到对应页”这个功能是在子组件中进行监听实现的,
子组件不能直接修改父组件的值,所以需要中转一下。在子组件中使用
currentPageLocal
(进行页码的显示或者是传递)
currentPage:{handler:function(value){this.currentPageLocal = value;},},
3.监听鼠标滚动控制左右翻页
在包裹epub内容的div上增加监听鼠标滚轮的动作
@wheel="handleWheel"
handleWheel(event){if(event.deltaY <0){// console.log("往上");this.prevPage();}elseif(event.deltaY >0){// console.log("往下");this.nextPage();}},
优化了一下上面的左右翻页代码,如下:
ps:还是存在一些问题的,滚动翻页可能会导致页码和实际的页码对不上?不知道是哪里的逻辑错了。
prevPage(){if(this.rendition){
console.log("prev");this.rendition.prev();this.currentPage--;// 向前翻页时更新 currentPageif(this.currentPage <=1){this.currentPage =1;}}},nextPage(){if(this.rendition){try{this.rendition.next();this.currentPage++;// 向后翻页时更新 currentPageif(this.currentPage >=this.totalPages){this.currentPage =this.totalPages;}}catch(error){
console.log("EPUB 下一页出错:", error);alert("出错,请重试或检查 EPUB 文件格式。");}}},
4.高亮选中文本(不保存版)
ps:如果是跨行的文本,无法高亮会报错,最好排除一下,加一个用户提示。
//读取epub信息并挂载asyncreadEpubMes(file){this.book =ePub(file);awaitthis.book.ready;// console.log(this.book);if(this.book !==null&&typeofthis.book !=="undefined"){this.rendition =this.book.renderTo("read",{flow:"paginated",width:"100%",height:"100%",});this.rendition.display();// 添加选中事件监听器let lastChoosed ="";this.rendition.on("selected",(cfiRange, contents)=>{// 获取选中范围let range = contents.window.getSelection().getRangeAt(0);if(range.toString()!= lastChoosed){
console.log(range.toString());
lastChoosed = range.toString();}// 创建标记let marker = document.createElement("span");
marker.style.backgroundColor ="yellow";// 设置高亮颜色
marker.classList.add("highlight");// 可选,添加自定义类名// 将选中范围用标记包裹起来
range.surroundContents(marker);});// 获取locations对象 epubjs的钩子函数实现this.book.ready
.then(()=>{this.navigation =this.book.navigation;returnthis.book.locations.generate();}).then((result)=>{this.locations =this.book.locations;this.bookAvailable =true;// 获取总页数this.totalPages =this.locations.length();// console.log("Total pages: " + this.totalPages);});}},
后记
关于epubjs写得不是很详细,因为是在前面的源码上二改的。所需要的功能也不多。(单页+上下滑动显示不知道怎么实现)
关于pdf的预览,其实直接用vue-pdf也是不错的。
后面补充吧。
版权归原作者 Lana学习中 所有, 如有侵权,请联系我们删除。