PDF.js、ztree使用整理

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;   
},
上一篇:985 道 Java 面试题细分 6本PDF ,冲刺36*18k薪资


下一篇:【报告分享】2021年香水品牌社媒营销分析报告-果集数据(附下载)