pdf.js内部的按钮上传、定位、浏览功能的方法
优采云 发布时间: 2021-05-06 23:03pdf.js内部的按钮上传、定位、浏览功能的方法
这部分是我们公司之前需要实现的pdf上传,定位和浏览功能。就像以前的博客一样,我遇到了很多问题。使用的主要js是pdf.js,为了实现浏览上载的pdf,以前的博客记录了跨域问题(跨域问题是非常重要的,因为通用文件服务器和项目服务器是分开的),记录是否实现了行定位功能。
最初,我不打算使用行定位,因为我之前曾考虑过它,而且它一无是处,因为pdf.js主要单击缩略图以找到相应的页码来实现页码跳转。由于用户无法单击pdf.js内的按钮,因此需要在外部添加按钮(相当于定位点功能)。主要功能点:锚点设置和锚点定位。
下面我只讨论行定位的方法:
思考:pdf.js具有目录功能,单击目录中的标题以实现行定位,这启发了我思考行定位的实现。主页使用页面F12检查目录位置的链接,发现它是一串代码(我不知道哪种格式),我将其复制并在网页上进行了转码,并找到了如下格式:
#[{"num":23,"gen":0},{"name":"XYZ"},74,769,0]
#[{"num":46,"gen":0},{"name":"XYZ"},74,442,0]
这是与两个标题相对应的代码转换代码。我发现两个地方不同。一个是num的值,另一个是倒数第二个数字。我接下来去。寻找源代码,一个接一个的控制台,我终于在viewer.js的9285行中找到了线索(因为每个版本中的行数不同,以下是我复制的js方法,因为加密的计算机可以'不截屏,仅截取代码):
key: '_updateLocation',
value: function _updateLocation(firstPage) {
var currentScale = this._currentScale;
var currentScaleValue = this._currentScaleValue;
var normalizedScaleValue = parseFloat(currentScaleValue)
...........
滚动页面时,此方法的控制台方法将使用此方法。此方法背后有几个非常重要的参数。
this._location = {
pageNumber: pageNumber,
scale: normalizedScaleValue,
top: intTop,
left: intLeft,
rotation: this._pagesRotation,
pdfOpenParams: pdfOpenParams
};
通过打印,可以发现pageNumber是当前页码,而intTop是代码更改数量中倒数第二个参数,它被解释为高度(哈哈,现在我知道了不是记录的行,而是当前记录(通过页码高度实现的“行定位”),现在第一个参数在那里,主要目标是该num的值,与num的值完全不同我们在页面上看到的值,我猜它必须是json或数组。与键值相对应的页码是什么,然后我沿着藤蔓通过此方法找到了大本营:
{
key: 'cachePageRef',
value: function cachePageRef(pageNum, pageRef) {
if (!pageRef) {
return;
}
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
this._pagesRefCache[refStr] = pageNum;
}
}, {
key: '_cachedPageNumber',
value: function _cachedPageNumber(pageRef) {
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
return this._pagesRefCache && this._pagesRefCache[refStr] || null;
}
},
我这一边大约是7139行(viewer.js),这两种方法非常重要,一种是页码(在下面),另一种是创建的键值格式的代码(在上部),这是通过控制台了解的,当您加载pdf文件时,您将调用上述方法以将页码与代码进行匹配(相应的格式为“ 27 0 R”-“ 4”,其中4为值是页面数字,前面的键是代码。
到目前为止,感觉就像(将云朵拉开,看到蓝天)。以下是收购。滚动上面提到的9,000行以上的页面的方法,几个参数,其中intTop是我们需要的高度值,并且需要通过该键值获取页码,因此我开始修改源代码代码。
我们需要实时获取当前页面的数据
this._location = {
pageNumber: pageNumber,
scale: normalizedScaleValue,
top: intTop,
left: intLeft,
rotation: this._pagesRotation,
pdfOpenParams: pdfOpenParams
};
//下方是我添加的代码(这里你需要在viewer.html页面中加入二个隐藏的input,id为page_top和page_cache)
var page_top = document.getElementById("page_top");
page_top.value = this._location.top;
var page_cache = document.getElementById("page_cache");
page_cache.value = this.getPageCache(this._location.pageNumber);
最后一行的getPageCache方法是我修改的源代码:
this._location = {
pageNumber: pageNumber,
scale: normalizedScaleValue,
top: intTop,
left: intLeft,
rotation: this._pagesRotation,
pdfOpenParams: pdfOpenParams
};
//下方是我添加的代码(这里你需要在viewer.html页面中加入二个隐藏的input,id为page_top和page_cache)
var page_top = document.getElementById("page_top");
page_top.value = this._location.top;
var page_cache = document.getElementById("page_cache");
page_cache.value = this.getPageCache(this._location.pageNumber);
}
},{//下面是我添加的方法
//这个方法用来获取对应num的页码cache
key:'getPageCache',
value:function getPageCache(pageNum){
//循环结果(这里的page_cache是一个数组,下面细说)
var str = JSON.stringify(page_cache);
// console.log("格式为:"+typeof(JSON.parse(str)))
// console.log("json的数据:"+str)
for(var key in JSON.parse(str)){
if(JSON.parse(str)[key]==pageNum){
return key;
}
}
}
我们在上面提到了键值格式数据,因为它不在代码块中,所以我在js顶部添加了一个全局变量page_cache
//定义全局变量 去接受页码对应编码值
var page_cache = [];
然后在页面加载pdf时为该数组分配一个值:
{
key: 'cachePageRef',
value: function cachePageRef(pageNum, pageRef) {
if (!pageRef) {
return;
}
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
this._pagesRefCache[refStr] = pageNum;
//当赋值完毕之后,给全局赋值,这样我就获取到这个编码了
page_cache = this._pagesRefCache;
}
}, {
key: '_cachedPageNumber',
value: function _cachedPageNumber(pageRef) {
var refStr = pageRef.num + ' ' + pageRef.gen + ' R';
return this._pagesRefCache && this._pagesRefCache[refStr] || null;
}
},
以这种方式,如上所述,通过此全局情况获得了相应的代码值。 (这是采集的结束(设置锚点))
另外:有些人可能无法在iframe下获取文件,请将此信息发送给我:
//这个是子页面
//js
top = $("#iframe01").contents().find("#page_top").val();
cache = $("#iframe01").contents().find("#page_cache").val().split(" ")[0];
console.log("父页面获取的top:"+$("#iframe01").contents().find("#page_top").val());
console.log("父页面获取的页码编码:"+$("#iframe01").contents().find("#page_cache").val());
通过这种方式,可以获得该代码中num和height的值。
以下是定位的实现(锚点定位):直接上传代码
//html
点击定位1
点击定位2
//jq
//这个才是定位
$(".set1").click(function(){
$(".set2").click();
//始终在页面只有一个是模拟添加的a标签
if($("#iframe01").contents().find(".addLink").length!=0){
$("#iframe01").contents().find(".addLink").remove();
}
//创建一个模拟目录中的标题a标签
str = "<a hidden:'hidden' href='"
+ '#[{"num":'+cache+',"gen":0},{"name":"XYZ"},74,'+top+',0]'
+ "'class='internalLink addLink' id='p37318'>
</a>";
//添加到子页面中
//先判断是否有 没有再添加 有就不添加
if($("#iframe01").contents().find("#p37318").length==0){
$("#iframe01").contents().find("body").append(str);
}
//模拟目录a标签的点击事件
$("#iframe01").contents().find("#p37318").find("p")[0].click();
})
//这个是假的
$(".set2").click(function(){
if($("#iframe01").contents().find(".addLink").length!=0){
$("#iframe01").contents().find(".addLink").remove();
}
str = "<a href='"
+ '#[{"num":17,"gen":0},{"name":"XYZ"},74,192,0]'
+ "'class='internalLink addLink' id='p17192'><p>GG</a>";
if($("#iframe01").contents().find("#p17192").length==0){
$("#iframe01").contents().find("body").append(str);
}
$("#iframe01").contents().find("#p17192").
find("p")[0].click();
})</p>
想法:找到目录标签的事件和类,在后台传输的数据具有这两个参数,创建一个类似的标签,将参数放入,然后将其放入子页面,并在单击时找到我们。新添加的标签触发单击以实现跳转,而set1此处为跳转。因为在我本地滚动时一键单击,再次单击将不起作用,无效。因此,添加了一个隐藏的单击,并且每次单击都会首先触发一个隐藏的单击。发现可用。
许多人都遇到过这种问题。你不用再找我了设置锚点并通过所需的内容跳转到锚点。我在github上写了一个小演示。如果您有兴趣,可以下载并尝试
整个模拟行定位已完成。我花了整整一天的时间,但最终结果仍然让我感到非常满意。由于该项目的源代码无法发布,因此我只能在github上上传一个简单的演示,有兴趣的人可以下载它。如有任何疑问,可以留言。