js获取网页鼠标选中部分的内容,包含html代码

function getSelectedContents(){

   if (window.getSelection) { //chrome,firefox,opera

       var range=window.getSelection().getRangeAt(0);

       var container = document.createElement('div');

       container.appendChild(range.cloneContents());

       return container.innerHTML;

       //return window.getSelection(); //只复制文本

   }

   else if (document.getSelection) { //其他

       var range=window.getSelection().getRangeAt(0);

       var container = document.createElement('div');

       container.appendChild(range.cloneContents());

       return container.innerHTML;

       //return document.getSelection(); //只复制文本

   }

   else if (document.selection) { //IE特有的

       return document.selection.createRange().htmlText;

       //return document.selection.createRange().text; //只复制文本

   }

}

<think>我们想要在PDF.js中实现一个功能:当用户用鼠标选中文本时,对选中部分添加一个遮盖(比如半透明的背景色),或者取消选中时的遮盖。 但是,请注意:PDF.js默认已经支持文本选中(高亮显示),不过这里的需求可能是要自定义选中的样式,或者是在选中时添加额外的遮盖效果。 实现思路: 1. 我们可以通过CSS来改变默认的选中样式。但是,如果是要在选中时添加一个遮盖层(例如一个div覆盖在选中的区域上),则需要更复杂的操作。 2. PDF.js选中文本时会生成一个包含选中文本的div,并添加类名(如`.textLayer ::selection`)。我们可以通过CSS修改这个选择器的样式来改变选中背景。 3. 但是,如果需求是“遮盖”即覆盖一个层,那么可能需要监听文本选择事件,然后动态创建div覆盖在选中区域上。然而,这样做有几个难点: - 选中区域可能跨越多行,甚至跨越分页。 - 需要精确计算每个选中字符的位置和尺寸,然后合并这些区域形成一个或多个矩形覆盖层。 考虑到复杂度,我们首先考虑使用CSS修改选中样式。如果需求是自定义选中颜色,那么只需要CSS即可。 然而,如果需求是“取消选中时的遮盖”,可能是指取消默认的选中高亮,那么我们可以通过CSS将选中的背景色设置为透明。 但是,问题描述是“增加鼠标选中遮盖部分内容”或者“取消选中”,这可能是两个需求: a) 增加遮盖:在选中时添加一个自定义样式的遮盖(比如不同于浏览器默认的蓝色高亮)。 b) 取消选中:取消选中的高亮效果。 下面分别给出两种解决方案: 方案一:使用CSS自定义选中样式(简单方案) ```css /* 修改选中的背景色和文字颜色 */ .textLayer ::selection { background: rgba(255, 0, 0, 0.3); /* 半透明红色背景 */ color: white; /* 文字颜色 */ } ``` 方案二:动态创建遮盖层(复杂方案) 如果需求不仅仅是改变颜色,而是要做更复杂的遮盖(比如加一个图标、边框等),则需要动态创建遮盖层。 步骤: 1. 监听文本选择事件(可以使用document的selectionchange事件,或者PDF.js提供的textlayerrendered事件后对文本层添加事件)。 2. 当选择发生时,获取选中的范围(Range)和位置信息。 3. 遍历选中的文本节点,计算每个字符的位置(PDF.js的文本层每个字符通常是一个span,有绝对定位)。 4. 合并这些矩形区域(可能会重叠,需要合并成大的矩形)。 5. 创建div元素,设置定位和样式,覆盖在选中的区域上。 但是,这个方案非常复杂,而且性能开销大,尤其是当选中大段文本时。另外,PDF.js的文本层是绝对定位的,并且每个字符都有位置,所以计算矩形区域是可行的,但要注意跨页的情况。 由于复杂度高,这里我们只给出一个简化的示例,仅处理单行选中的情况,并且不考虑跨页。实际应用中需要更完善的算法。 鉴于以上,我们先给出一个简单的CSS方案,然后给出一个动态创建遮盖层的示例(简化版)。 如果需求是取消选中,则可以通过CSS将背景设置为透明: ```css .textLayer ::selection { background: transparent; } ``` 下面我们重点实现一个动态创建遮盖层的简化示例(注意:这只是一个基础示例,实际使用需要完善): 步骤: 1. 在PDF.js渲染完成后,获取文本层(.textLayer)。 2. 监听文本层的鼠标事件(如mouseup)来判断是否有选中。 3. 获取选中的范围(window.getSelection())。 4. 如果选中不为空,遍历选中的节点,计算位置和尺寸。 5. 创建一个div,将其定位到选中的区域。 注意:由于PDF.js的文本层是绝对定位,并且每个字符都是独立的span,我们可以通过选中范围的起始和结束节点,以及偏移量来获取选中的字符节点。 代码示例(简化版,仅处理连续选中且在同一行内): ```javascript // 假设在PDFViewer加载完成后执行 const viewer = document.getElementById('viewer'); const textLayer = viewer.querySelector('.textLayer'); textLayer.addEventListener('mouseup', function() { // 清除之前创建的遮盖 clearHighlights(); let selection = window.getSelection(); if (selection.isCollapsed) { return; } let range = selection.getRangeAt(0); let rects = range.getClientRects(); for (let i = 0; i < rects.length; i++) { let rect = rects[i]; createHighlight(rect); } }); function createHighlight(rect) { let highlight = document.createElement('div'); highlight.style.position = 'absolute'; highlight.style.backgroundColor = 'rgba(255, 0, 0, 0.3)'; highlight.style.pointerEvents = 'none'; // 避免遮盖事件 // 根据rect的位置和尺寸设置 highlight.style.left = (rect.left + window.scrollX) + 'px'; highlight.style.top = (rect.top + window.scrollY) + 'px'; highlight.style.width = rect.width + 'px'; highlight.style.height = rect.height + 'px'; document.body.appendChild(highlight); // 注意:最好添加到文本层的父元素,并考虑相对定位容器 } function clearHighlights() { let highlights = document.querySelectorAll('.pdf-highlight'); // 假设给创建的div加一个类名 highlights.forEach(el => el.remove()); } ``` 但是,上面的代码有几个问题: - 它使用了相对于视口的坐标(getClientRects返回的是视口坐标),而PDF.js的文本层是绝对定位在一个容器内的,这个容器可能有偏移和缩放。 - 没有考虑多个范围(虽然通常只有一个范围)。 - 没有处理跨行的情况(getClientRects会返回多个矩形,所以循环创建多个div,但这样会创建很多小div,性能不好,应该合并相邻矩形)。 因此,更健壮的做法是: - 获取文本层容器的位置,将视口坐标转换为相对于文本层容器的坐标。 - 合并相邻或重叠的矩形(水平方向合并,垂直方向如果在同一行也可以合并,但跨行则不行)。 由于合并矩形的算法较为复杂,这里不展开。我们可以使用一个库,或者只处理简单情况。 另外,注意在PDF.js缩放或滚动时,这些遮盖层的位置需要更新,否则会错位。所以这个方案需要监听页面变化并重新计算,复杂度很高。 因此,建议优先考虑CSS方案,除非有特殊需求。 总结: 1. 如果只是改变选中颜色,用CSS。 2. 如果需要更复杂的遮盖,且可以接受一定的性能开销和复杂度,则用动态创建遮盖层的方法,并注意处理坐标转换和更新。 下面给出一个相对完整的动态遮盖示例,考虑到了文本层容器的偏移和缩放(假设文本层容器是.textLayer,且其position为absolute): ```javascript // 在PDFViewer渲染完成后执行 const textLayer = document.querySelector('.textLayer'); textLayer.addEventListener('mouseup', function() { clearHighlights(); let selection = window.getSelection(); if (selection.isCollapsed) { return; } let range = selection.getRangeAt(0); let rects = range.getClientRects(); let containerRect = textLayer.getBoundingClientRect(); for (let i = 0; i < rects.length; i++) { let rect = rects[i]; // 将视口坐标转换为相对于文本层容器的坐标 let relativeRect = { left: rect.left - containerRect.left + textLayer.scrollLeft, top: rect.top - containerRect.top + textLayer.scrollTop, width: rect.width, height: rect.height }; createHighlight(relativeRect, textLayer); } }); function createHighlight(rect, container) { let highlight = document.createElement('div'); highlight.className = 'pdf-highlight'; // 用于清除 highlight.style.position = 'absolute'; highlight.style.backgroundColor = 'rgba(255, 0, 0, 0.3)'; highlight.style.pointerEvents = 'none'; highlight.style.left = rect.left + 'px'; highlight.style.top = rect.top + 'px'; highlight.style.width = rect.width + 'px'; highlight.style.height = rect.height + 'px'; container.appendChild(highlight); // 添加到文本层内,这样位置是相对于文本层容器的 } function clearHighlights() { let highlights = document.querySelectorAll('.pdf-highlight'); highlights.forEach(el => el.remove()); } ``` 注意:这个示例仍然没有合并矩形,所以选中的每一段都会创建一个div。如果选中很长,可能会有很多div。另外,当PDF缩放或滚动时,这些遮盖层不会自动更新位置,所以需要监听页面变化并重新计算。 考虑到复杂性和性能,建议仅在确实需要时使用动态遮盖,否则使用CSS方案。 最后,根据问题,我们给出两种方案的代码,并解释。 方案选择: 如果只是改变颜色,用CSS方案;如果要有更复杂的遮盖效果,用动态创建div方案。 代码示例(CSS方案): ```css /* 自定义选中样式 */ .textLayer ::selection { background: rgba(255, 0, 0, 0.3); color: white; } ``` 代码示例(动态遮盖方案): ```javascript // 在PDF.js渲染完成后,绑定事件 document.addEventListener('textlayerrendered', function (event) { // 每个文本层渲染完成后都会触发,event.detail.pageNumber const textLayer = event.detail.source.textLayerDiv; // 清除之前的监听器,避免重复 textLayer.removeEventListener('mouseup', handleMouseUp); textLayer.addEventListener('mouseup', handleMouseUp); }); function handleMouseUp() { // 清除之前创建的遮盖(在当前文本层内) clearHighlights(this); // this指向textLayer let selection = window.getSelection(); if (selection.isCollapsed) { return; } let range = selection.getRangeAt(0); let rects = range.getClientRects(); let containerRect = this.getBoundingClientRect(); for (let i = 0; i < rects.length; i++) { let rect = rects[i]; // 转换为相对于文本层的坐标 let relativeRect = { left: rect.left - containerRect.left, top: rect.top - containerRect.top, width: rect.width, height: rect.height }; createHighlight(relativeRect, this); } } function createHighlight(rect, container) { let highlight = document.createElement('div'); highlight.className = 'pdf-highlight'; highlight.style.position = 'absolute'; highlight.style.backgroundColor = 'rgba(255, 0, 0, 0.3)'; highlight.style.pointerEvents = 'none'; highlight.style.left = rect.left + 'px'; highlight.style.top = rect.top + 'px'; highlight.style.width = rect.width + 'px'; highlight.style.height = rect.height + 'px'; container.appendChild(highlight); } function clearHighlights(container) { let highlights = container.querySelectorAll('.pdf-highlight'); highlights.forEach(el => el.remove()); } ``` 注意:动态遮盖方案需要在每个文本层上单独处理,因为每个文本层是独立的。这里使用了PDF.js的textlayerrendered事件,确保每个文本层渲染完成后绑定事件。 但是,这段代码仍然有优化空间,比如合并矩形区域、处理跨页等。同时,当页面缩放或滚动时,需要重新计算位置(这里没有实现)。 由于PDF.js可能动态渲染页面(比如滚动时),所以还需要在页面滚动或缩放时清除遮盖层,或者重新计算位置。这可能会很复杂。 因此,根据需求选择方案。 §§相关问题§§: 1. 如何修改PDF.js默认的文本选中颜色? 2. 在PDF.js中,如何监听文本选中事件? 3. 如何实现跨多行的文本选中遮盖合并? 4. 当PDF页面缩放时,如何更新动态创建的遮盖层位置?</think>### 在 PDF.js 中实现选中遮盖或取消选中效果 #### 解决方案分析 在 PDF.js 中实现选中遮盖或取消选中效果,需要操作 PDF.js 的文本层(Text Layer)。以下是两种实现方式: 1. **添加选中遮盖**:通过修改选中文本的 CSS 样式 2. **取消选中效果**:通过禁用文本选择或重置选中样式 #### 实现代码与解释 ##### 1. 添加选中遮盖(半透明背景色) ```javascript // 在文本层渲染完成后添加自定义样式 pdfViewer.eventBus.on('textlayerrendered', event => { const textLayer = event.source.textLayerDiv; // 添加自定义选中样式 const style = document.createElement('style'); style.innerHTML = ` .textLayer ::selection { background: rgba(255, 0, 0, 0.3) !important; /* 半透明红色遮盖 */ } `; textLayer.appendChild(style); }); ``` **代码解释**: - 监听 `textlayerrendered` 事件确保文本层已渲染 - 创建 `<style>` 元素注入自定义 CSS - `::selection` 伪元素选择器修改选中文本样式 - `rgba(255, 0, 0, 0.3)` 表示半透明红色背景(可自定义颜色) ##### 2. 取消选中效果(禁用文本选择) ```javascript // 完全禁用文本选择 pdfViewer.eventBus.on('textlayerrendered', event => { const textLayer = event.source.textLayerDiv; // 方法1:通过CSS禁用选择 textLayer.style.userSelect = 'none'; // 方法2:通过事件阻止默认行为 textLayer.addEventListener('selectstart', e => e.preventDefault()); }); ``` **代码解释**: - **方法1**:使用 `user-select: none` CSS 属性禁用文本选择 - **方法2**:监听 `selectstart` 事件阻止选择行为 - 两种方法都可实现取消选中效果,推荐 CSS 方法更高效 #### 完整示例(整合两种功能) ```html <!DOCTYPE html> <html> <head> <title>PDF.js 选中控制</title> <script src="//mozilla.github.io/pdf.js/build/pdf.js"></script> <style> #viewerContainer { position: relative; width: 80%; margin: 20px auto; } .button-group { text-align: center; margin: 20px; } button { padding: 10px 20px; margin: 0 10px; cursor: pointer; } </style> </head> <body> <div class="button-group"> <button id="enableHighlight">启用选中遮盖</button> <button id="disableSelection">禁用文本选择</button> <button id="reset">重置默认效果</button> </div> <div id="viewerContainer"> <canvas id="pdfCanvas"></canvas> </div> <script> // PDF.js 配置 const pdfjsLib = window['pdfjs-dist/build/pdf']; pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js'; // 初始化查看器 const container = document.getElementById('viewerContainer'); const pdfViewer = new pdfjsLib.PDFViewer({ container: container }); // 加载示例PDF const loadingTask = pdfjsLib.getDocument({ url: '//mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf' }); loadingTask.promise.then(pdf => { pdfViewer.setDocument(pdf); }); // 功能控制 let customStyle = null; document.getElementById('enableHighlight').addEventListener('click', () => { resetEffects(); // 添加选中遮盖 customStyle = document.createElement('style'); customStyle.innerHTML = ` .textLayer ::selection { background: rgba(0, 100, 255, 0.3) !important; } `; document.head.appendChild(customStyle); }); document.getElementById('disableSelection').addEventListener('click', () => { resetEffects(); // 禁用文本选择 const textLayers = document.querySelectorAll('.textLayer'); textLayers.forEach(layer => { layer.style.userSelect = 'none'; }); }); document.getElementById('reset').addEventListener('click', resetEffects); function resetEffects() { // 移除自定义样式 if (customStyle) { customStyle.remove(); customStyle = null; } // 恢复文本选择 const textLayers = document.querySelectorAll('.textLayer'); textLayers.forEach(layer => { layer.style.userSelect = ''; }); } </script> </body> </html> ``` **功能说明**: 1. **启用选中遮盖**:为选中的文本添加蓝色半透明背景 2. **禁用文本选择**:完全阻止用户选择文本 3. **重置效果**:恢复 PDF.js 默认的选中样式 **关键点**: - 通过操作 `.textLayer ::selection` 伪元素自定义选中样式 - 使用 `user-select: none` 禁用文本选择 - 在 `textlayerrendered` 事件中操作确保文本层已渲染 - 动态创建/移除样式元素实现效果切换 #### 注意事项 1. `!important` 声明用于覆盖 PDF.js 默认样式 2. 使用 RGBA 颜色值控制透明度(0.3 = 30% 不透明度) 3. 跨浏览器兼容性:现代浏览器均支持 `::selection` 伪元素 4. 对于复杂需求(如精确选区计算),可使用 PDF.js 的 `getTextContent()` API 获取文本位置信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值