PDF.js相关操作
切换pdf后,保存pdf比例
在viewer.js中,setInitialView方法
//获取url参数
var _url = window.location.search;
if (_url === '') {
_url = window.location.href;
}
//获取参数
var obj = {};
var reg = /[?&][^?&]+=[^?&]+/g;
var arr = _url.match(reg);
if (arr) {
arr.forEach(function (item) {
var tempArr = item.substring(1).split('=');
var key = decodeURIComponent(tempArr[0]);
var val = decodeURIComponent(tempArr[1]);
obj[key] = val;
});
}
//获取参数,修改展示比例 通过url传入type:page-actual/page-fit/page-width/50%-400%
if (!this.pdfViewer.currentScaleValue) {
this.pdfViewer.currentScaleValue = obj.type ? obj.type : _ui_utils.DEFAULT_SCALE_VALUE;
}
加载pdf后,使用pdf自带搜索功能
在viewer.js中,setInitialView方法
// obj为url参数对象
if(obj.search){
PDFViewerApplication.findController.executeCommand('find', {
query: obj.search,
phraseSearch: true,
caseSensitive: true,
highlightAll: true
});
}
监听pdf鼠标滚轮事件
在viewer.js中,webViewerWheel方法
// 通过postMessage方式 传递到使用组件中
var myDiv = document.querySelector("#viewerContainer")
var divTop = myDiv.scrollTop;
var divHeight = myDiv.clientHeight;
var divScrollHeight = myDiv.scrollHeight;
if (divTop + divHeight >= divScrollHeight || document.querySelector("#viewerContainer").scrollTop == 0) {
//向下滚动
if (divTop + divHeight >= divScrollHeight && evt.deltaY > 0) {
window.parent.postMessage({
cmd: 'next'
}, '*');
} else if (document.querySelector("#viewerContainer").scrollTop == 0 && evt.deltaY < 0) {
window.parent.postMessage({
cmd: 'prev'
}, '*');
}
}
PDF选中文字
if (this.getSelection) {
// 鼠标选中方法
const selectionObj = this.getSelection();
// 选中文字
let xzclnr = selectionObj.toString();
// 是否存在选中内容
if (xzclnr) {
// 设置是否可以标记
this.isDisabled = false;
// 选中范围
const rangeObj = selectionObj.getRangeAt(0);
// 文字开始位置
const textStart = rangeObj.startOffset;
// 文字结束位置
const textEnd = rangeObj.endOffset;
// 选中pdf第几页
const xzclym = this.getElementParentNode(selectionObj.focusNode);
// 判断选择部分是否标记过
const isHighLight = rangeObj.commonAncestorContainer;
if (isHighLight.nodeType == 3 && isHighLight.parentNode.nodeName == 'SPAN') {
this.isDisabled = true;
} else {
const docFragment = rangeObj.cloneContents();
try {
const _docFragment = [].slice.apply(docFragment.childNodes);
_docFragment.forEach((item, index) => {
const _divs = [].slice.apply(item.childNodes);
_divs.forEach(i => {
if ($(i)[0].tagName == 'SPAN') {
_this.isDisabled = true;
throw new Error('EndIterative');
} else if ($(i)[0].parentNode.tagName == 'SPAN') {
_this.isDisabled = true;
throw new Error('EndIterative');
}
});
});
} catch (e) {
if (e.message != 'EndIterative') {
throw e;
}
}
}
// 选中开始div元素
const startContainer = rangeObj.startContainer;
// 选中结束div元素
const endContainer = rangeObj.endContainer;
// 判断笔记是否跨页 ($(startContainer).parent().attr("data-page-number")处理ie浏览器兼容)
const _startPage = this.getElementParentNode(startContainer) ? this.getElementParentNode(startContainer) : $(startContainer).parent()
.attr('data-page-number');
const _ednPage = this.getElementParentNode(endContainer) ? this.getElementParentNode(endContainer) : $(endContainer).parent()
.attr('data-page-number');
if (_startPage != _ednPage) {
this.isDisabled = true;
}
// 鼠标选中方法
let divEnd = $(endContainer.nodeType == 1 ? endContainer : endContainer.parentNode).index();
// 兼容ie选中结束dom为textLayer元素时
if (endContainer.className == 'textLayer') {
const commonAncestorContainer = [].slice.apply(rangeObj.commonAncestorContainer.children);
const divs = rangeObj.cloneContents().childNodes;
const _left = divs[divs.length - 1].style.left;
const _top = divs[divs.length - 1].style.top;
for (let index = 0; index < commonAncestorContainer.length; index++) {
const item = commonAncestorContainer[index];
if ((_left == item.style.left) && (_top == item.style.top)) {
divEnd = $(item).index();
break;
}
}
}
// 回显使用
this.pdfBjInfo = {
'divStart': $(startContainer.nodeType == 1 ? startContainer : startContainer.parentNode).index(), // 圈选div起点
'divEnd': divEnd, // 圈选div终点
'textStart': textStart, // 圈选文本起点
'textEnd': textEnd, // 圈选文本终点
'xzclym': xzclym || 1 // 选中pdf第几页
};
// console.log(startIndex)
// console.log(endIndex)
// console.log(textStart)
// console.log(textEnd)
// console.log(xzclym)
} else {
selectionObj.removeAllRanges();
}
}
获取当前选中pdf属于第几页
// 当前选中元素
getElementParentNode(el) {
let dom = null;
let current = el.parentNode;
while (current.className != 'page') {
current = current.parentNode; // 继续找父元素
dom = $(current).attr('data-page-number');
}
return dom;
}
pdf选中文字高亮
//高亮pdf文本
function updateHighlightInfo(highLightInfo, spanId) {
const _this = window.textLayer ? window.textLayer : this;
if ($('.fd-annotation-mark').length > 0) {
$('.fd-annotation-mark').contents()
.unwrap();
}
if (highLightInfo != null && highLightInfo.length > 0) {
if (_this && _this.renderingDone) {
highLightInfo.forEach(function (hItme) {
const _textLayerDivs = $('.textLayer')[hItme.xzclym - 1];
const _divs = [].slice.apply(_textLayerDivs.children);
// 此时匹配内容存在多个div中且在本页
if ((hItme.divEnd - hItme.divStart) >= 1) {
const _textDivs = _divs.slice(hItme.divStart, hItme.divEnd + 1);
// 将pdf数组分为2部分开始、结束
if (_textDivs.length < 3) {
var _startArr = _divs.slice(hItme.divStart, hItme.divStart + 1);
// 开始部分找到笔记textStart往后内容全部替换
_startArr.forEach(function (pdfItem) {
pdfItem.innerHTML = pdfItem.innerHTML.replace(pdfItem.textContent.substr(hItme.textStart != 0 ? hItme.textStart - 1 : 0, pdfItem.textContent.length), `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark start'>${pdfItem.innerHTML.substr(hItme.textStart, pdfItem.textContent.length)}</span>`);
});
// 结束数组
var _endArr = _divs.slice(hItme.divStart + 1, hItme.divEnd + 1);
// 结束部分textEnd以前全部替换
_endArr.forEach(function (pdfItem) {
if (hItme.textEnd > 0) {
pdfItem.innerHTML = pdfItem.innerHTML.replace(pdfItem.textContent.substr(0, hItme.textEnd == 0 ? pdfItem.textContent.length : hItme.textEnd), `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark end'>${pdfItem.innerHTML.substr(0, hItme.textEnd == 0 ? pdfItem.textContent.length : hItme.textEnd)}</span>`);
} else {
pdfItem.innerHTML = `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark end'>${pdfItem.textContent}</span>`;
}
});
} else {
// 将pdf数组分为3部分开始、中间、结束
var _startArr = _divs.slice(hItme.divStart, hItme.divStart + 1);
// 开始部分找到笔记textStart往后内容全部替换
_startArr.forEach(function (pdfItem) {
pdfItem.innerHTML = pdfItem.innerHTML.replace(pdfItem.textContent.substr(hItme.textStart != 0 ? hItme.textStart - 1 : 0, pdfItem.textContent.length), `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark start'>${pdfItem.innerHTML.substr(hItme.textStart, pdfItem.textContent.length)}</span>`);
});
// 中间数组
const _centerArr = _divs.slice(hItme.divStart + 1, hItme.divEnd);
// 中间部分全部替换
_centerArr.forEach(function (pdfItem) {
pdfItem.innerHTML = `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark center'>${pdfItem.textContent}</span>`;
});
// 结束数组
var _endArr = _divs.slice(hItme.divEnd, hItme.divEnd + 1);
// 结束部分textEnd以前全部替换
_endArr.forEach(function (pdfItem) {
if (hItme.textEnd > 0) {
pdfItem.innerHTML = pdfItem.innerHTML.replace(pdfItem.textContent.substr(0, hItme.textEnd == 0 ? pdfItem.textContent.length : hItme.textEnd), `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark end'>${pdfItem.innerHTML.substr(0, hItme.textEnd == 0 ? pdfItem.textContent.length : hItme.textEnd)}</span>`);
} else {
pdfItem.innerHTML = `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark end'>${pdfItem.textContent}</span>`;
}
});
}
} else {
// 此时匹配笔记内容存在于1个div
const _highLightArr = _divs.slice(hItme.divStart, hItme.divEnd + 1);
_highLightArr.forEach(function (pdfItem) {
pdfItem.innerHTML = pdfItem.innerHTML.replace(hItme.xzclnr, `<span spanattr='${hItme.bjbh}' spanid='${hItme.lybh}' class='fd-annotation-mark'>${hItme.xzclnr}</span>`);
});
}
});
bindPzMarkEvent();
spanId ? $(`[spanid='${spanId}']`).addClass('light') : null;
}
} else if ($('.fd-annotation-mark').length > 0) {
$('.fd-annotation-mark').remove();
}
}
ztree使用总结
滚动条定位
在jquery.ztree.core.js中,源码使用scrollIntoView方法将选中节点展示到可视区域,但是层级过深或者多次切换后,无法将选中节点展示到可视区域中且无法居中展示。
// 源码
scrollIntoView: function (setting, dom) {
support IE 7 / 8
if (typeof Element === 'undefined' || typeof HTMLElement === 'undefined') {
var contRect = setting.treeObj.get(0).getBoundingClientRect(),
findMeRect = dom.getBoundingClientRect();
if (findMeRect.top < contRect.top || findMeRect.bottom > contRect.bottom ||
findMeRect.right > contRect.right || findMeRect.left < contRect.left) {
dom.scrollIntoView();
}
return;
}
//CC-BY jocki84@googlemail.com, https://gist.github.com/jocki84/6ffafd003387179a988e
if (!Element.prototype.scrollIntoViewIfNeeded) {
Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {
"use strict";
function makeRange(start, length) {
return {
"start": start,
"length": length,
"end": start + length
};
}
function coverRange(inner, outer) {
if (
false === centerIfNeeded ||
(outer.start < inner.end && inner.start < outer.end)
) {
return Math.max(
inner.end - outer.length,
Math.min(outer.start, inner.start)
);
}
return (inner.start + inner.end - outer.length) / 2;
}
function makePoint(x, y) {
return {
"x": x,
"y": y,
"translate": function translate(dX, dY) {
return makePoint(x + dX, y + dY);
}
};
}
function absolute(elem, pt) {
while (elem) {
pt = pt.translate(elem.offsetLeft, elem.offsetTop);
elem = elem.offsetParent;
}
return pt;
}
var target = absolute(this, makePoint(0, 0)),
extent = makePoint(this.offsetWidth, this.offsetHeight),
elem = this.parentNode,
origin;
while (elem instanceof HTMLElement) {
// Apply desired scroll amount.
origin = absolute(elem, makePoint(elem.clientLeft, elem.clientTop));
elem.scrollLeft = coverRange(
makeRange(target.x - origin.x, extent.x),
makeRange(elem.scrollLeft, elem.clientWidth)
);
elem.scrollTop = coverRange(
makeRange(target.y - origin.y, extent.y),
makeRange(elem.scrollTop, elem.clientHeight)
);
// Determine actual scroll amount by reading back scroll properties.
target = target.translate(-elem.scrollLeft, -elem.scrollTop);
elem = elem.parentNode;
}
};
}
},
修改后
scrollIntoView: function (setting, dom) {
if (!dom) {
return;
}
// view.getElementTop(setting,dom) 获取当前元素距离根节点top距离
$("#"+setting.treeId).parent().scrollTop(view.getElementTop(setting,dom) - $("#"+setting.treeId).parent().height()/2)
}
// 采用递归方式获取元素距离根节点top距离
getElementTop:function(setting,el) {
var actualTop = el.offsetTop; //这是获取元素距父元素顶部的距离
var current = el.parentNode; //这是获取父元素
var currentId = current.id; //这是获取父元素id
while (currentId !== setting.treeId) { //当它上面有元素时就继续执行
actualTop += current.offsetTop; //这是获取父元素距它的父元素顶部的距离累加起来
current = current.parentNode; //继续找父元素
currentId = current.id; //继续找父元素
}
return actualTop;
},