马黑黑 发表于 2026-7-2 13:11

初识 Selection 对象

<style>
    .artBox { margin: 20px auto; font: normal 18px/28px sans-serif; max-width: 1200px; }
    .artBox mark { padding: 2px 6px; background: lightblue; }
    .artBox blockquote { padding: 14px; border: solid lightblue; border-width: 0 4px; border-radius: 10px; background: beige; }
    .artBox p { margin: 10px 0; }
    .mama { margin: 30px; width: 600px; border: 1px solid gray; border-radius: 10px; padding: 10px; }
</style>

<div class="artBox">
    <blockquote id="bq1" onclick="getSelectedText();">Selection 对象表示用户选择的文本范围或插入符号的当前位置。它代表页面中的文本选区,可能横跨多个元素。文本选区由用户按下鼠标左键不放并拖拽鼠标经过文字而产生。调用 window.getSelection() 方法可以获取 Selection 对象。</blockquote>
    <p><button onclick="showSelection();">演示:点击此按钮将会在上面的文本段落中随机创建选区</button></p>
    <p>正如文本开头引用框所介绍的,你也可以在上面的文本段落中自行选择任意文本。上面介绍 Selection 对象的引用框集成有一个功能:用鼠标手动选择任意文本,都会弹出一个 alert 窗口,窗口上展现被选择文本的相关信息。功能的实现仅使用了一个方法:<mark>selection.toString()</mark>,该方法返回选区内的完整文本,toString 是<b>转换为字符串</b>的意思。</p>
    <p><mark>window.getSelection()</mark> 方法返回的是一个 Selection(选区)对象,该对象拥有如下主要<b>属性</b>:</p>
    <ul>
      <li><b>anchorNode</b> :只读,返回选区<b>起点</b>所在的节点(Node)。anchor是“锚”之意,指选区开始时的定位点(鼠标按下时的那个点)</li>
      <li><b>anchorOffset</b> :只读,返回选区起点在 anchorNode 中的位置偏移量。需要注意两种情形:
            <ol>
                <li>如果 anchorNode 是文本节点、注释节点,返回锚点(anchor)到该节点中第一个字的字符个数</l>
                <li>如果 anchorNode 是元素节点,返回锚点(anchor)之前的同级节点总数</li>
            </ol>
      </li>
      <li><b>focusNode</b> :只读,返回选区终点所在的节点。focus意味“焦点”,这里指选区起点到终点的高亮区域</li>
      <li><b>focusOffset</b> :只读,返回选区终点在 focusNode 中的位置偏移量。需要注意两种情形:
            <ol>
                <li>如果 focusNode 是文本节点、注释节点,返回焦点(focus)到该节点中的第一个字的字符个数</li>
                <li>如果 focusNode 是元素节点,返回焦点(focus)之前的同级节点总数</li>
            </ol>
      </li>
      <li><b>isCollapsed</b> :只读,返回布尔值,表示选区的起始点和终点是否在同一个位置</li>
      <li><b></b> :只读,选区方向,返回forward(自左向右)或 backward(自右向左)</li>
      <li><b>rangeCount</b> :只读,返回选区所包含的连续范围(range)的数量</li>
    </ul>
    <p>【注意】选区有方向(direction),可以自左向右或自右向左,取决于用户按下左键后往左或往右拖曳。选区的方向直接影响锚和焦点的位置,自左向右时锚前、焦点后,自右向左锚后、焦点前。</p>
    <p>下面是获取选区对象属性值的简单演示:</p>
    <div class="mama" onmouseup="getSelectionAttributes();">
      <h3>请选择任意文本</h3>
      <p>这行是 <mark>id="mama"</mark> div 的p标签文本,里面有两个<mark>mark</mark>元素节点</p>
      <div>这行是 div 标签,里面的内容是纯文本</div>
    </div>
    <p>选区(Selection)对象的主要<b>方法</b>则有:</p>
    <ul>
      <li>getRangeAt :返回选区包含的指定区域(Range)的引用,即获取指定选区的范围</li>
      <li>collapse :将当前的选区折叠为一个点</li>
      <li>extend :将选区的焦点移动到一个特定的位置</li>
      <li>modify :修改当前的选区</li>
      <li>collapseToStart :将当前的选区折叠到起始点</li>
      <li>collapseToEnd :将当前的选区折叠到最末尾的一个点</li>
      <li>selectAllChildren :将某一指定节点的子节点框入选区</li>
      <li>addRange :一个区域(Range)对象将被加入选区</li>
      <li>removeRange :从选区中移除一个区域</li>
      <li>removeAllRanges :将所有的区域都从选区中移除</li>
      <li>deleteFromDocument :从页面中删除选区中的内容</li>
      <li>toString :返回当前选区的纯文本内容</li>
      <li>containsNode :判断某一个 Node 是否为当前选区的一部分</li>
    </ul>
    <p>选区(Selection)对象的方法很多需要配合 range 对象使用,如开头随机选择选区就用上了 range 对象。下例仅演示 toStrong 和 delecteFromDocument 方法:</p>
    <div id="mama" class="mama" onmouseup="getTextAndDelete(this);">选择本此方框内的任意文本会获取所选择的文本然后删除掉,直至删完为止(选择后如果没有弹出alert窗口,请再单击一下此方框)。全部删除文本内容后可单击下方按钮重置。</div>
    <p><button id="btnResetText">重置方框文本</button></p>
    <p><br></p>
    <p>【附】本文基于选区的核心JS代码(自动获取)</p>
    <div class="hEdiv"><pre id="pre1" class="hEpre"></pre></div>
</div>

<script id="js_1">
    // 创建随机选区
    function showSelection() {
      const sel = window.getSelection();
      const range = new Range();
      const len = bq1.textContent.length; // blockquote的文本长度
      let begin = Math.floor(Math.random() * len / 2);
      let end = Math.floor(Math.random() * len);
      if (begin === end) end += 2;
      if (begin > end) = ;
      range.setStart(bq1.firstChild, begin);
      range.setEnd(bq1.firstChild, end);
      sel.removeAllRanges();
      sel.addRange(range);
    }
   
    // 获取选区文本
    function getSelectedText() {
      const sel = window.getSelection();
      const msg = sel.isCollapsed ? '你没有选择任何文字' : `你选择的文字是:${sel.toString()}`;
      alert(msg);
    }
   
    // 获取选区属性信息
    function getSelectionAttributes() {
      const sel = window.getSelection();
      let res = '未选择任何文本';
      // 若有选择文本
      if (sel.rangeCount) {
            const dir = {forward: '自左向右', backward: '自右向左'}
            res = `选区相关属性信息 :
            
                anchorNode(起始节点):${sel.anchorNode}
                anchorOffset(选区起点在起始节点中的偏移量):${sel.anchorOffset}
                focusNode(终点节点):${sel.focusNode}
                focusOffset(选区终点在结束节点中的偏移量):${sel.focusOffset}
                direction(选区方向):${sel.direction}(${dir})
                isCollapsed(起始和结束节点是否同一个):${sel.anchorNode === sel.focusNode ? '同' : '不同'}
                rangeCount(选区范围):${sel.rangeCount}`;
      }
      alert(res);
    }
   
    // 获取选区文本并删除
    function getTextAndDelete() {
      const sel = window.getSelection();
      let str = '没有选择任何内容';
      if (sel.isCollapsed) return;
      alert(`选择的文本“${sel.toString()}”将被删除!`);
      sel.deleteFromDocument();
    }
</script>

<script type="module">
    import hl from 'https://638183.freep.cn/638183/web/js/hl.js';
    pre1.innerHTML = js_1.outerHTML.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
    const divs = document.querySelectorAll('.hEdiv');
    const pres = document.querySelectorAll('.hEpre');
    divs.forEach((div,idx) => hl.hl(div, pres));
   
    const rawtext = mama.innerText;
   
    btnResetText.onclick = () => mama.innerText = rawtext;
</script>

马黑黑 发表于 2026-7-2 13:18

Selection 对象和即将会介绍的 Range 对象是操作 DOM 的核心接口,两个对象紧密相连,其概念、属性、方法等都较难理解,希望包括本文在内的系列介绍文章能帮助大家了解、理解这两个对象

梦江南 发表于 2026-7-2 15:27

黑黑老师介绍的这些代码,学会了能很好地看懂帖子中代码的作用。就是不懂英文,学起来困难重重。

梦江南 发表于 2026-7-2 15:28

黑黑老师下午嚎!辛苦了!{:4_187:}

马黑黑 发表于 2026-7-2 19:38

梦江南 发表于 2026-7-2 15:27
黑黑老师介绍的这些代码,学会了能很好地看懂帖子中代码的作用。就是不懂英文,学起来困难重重。

不用担心,看看就行,做音画帖一般还用不上选区和范围对象。这是更为专业化的用途(例如着色版 pencil code 编辑器就必须用到这些)

马黑黑 发表于 2026-7-2 19:38

梦江南 发表于 2026-7-2 15:28
黑黑老师下午嚎!辛苦了!

晚上嚎!

梦江南 发表于 2026-7-2 20:05

马黑黑 发表于 2026-7-2 19:38
不用担心,看看就行,做音画帖一般还用不上选区和范围对象。这是更为专业化的用途(例如着色版 pencil co ...

谢谢黑黑老师回复,看看也是学习。{:4_187:}

梦江南 发表于 2026-7-2 20:06

马黑黑 发表于 2026-7-2 19:38
晚上嚎!

黑黑老师晚上嚎!

红影 发表于 2026-7-2 22:22

感觉这个有点繁琐,简单的拖曳鼠标的选择,竟然里面有这么多说道。
感谢黑黑的教学,学习了{:4_187:}

杨帆 发表于 2026-7-2 23:05

真正理解Selection 对象并不容易呢,谢谢马老师条理清晰、逻辑缜密的讲授{:4_190:}

马黑黑 发表于 2026-7-2 23:56

杨帆 发表于 2026-7-2 23:05
真正理解Selection 对象并不容易呢,谢谢马老师条理清晰、逻辑缜密的讲授

对,很抽象

马黑黑 发表于 2026-7-2 23:57

红影 发表于 2026-7-2 22:22
感觉这个有点繁琐,简单的拖曳鼠标的选择,竟然里面有这么多说道。
感谢黑黑的教学,学习了

嗯,这事很难理解的知识

马黑黑 发表于 2026-7-2 23:57

梦江南 发表于 2026-7-2 20:06
黑黑老师晚上嚎!

都嚎都嚎

马黑黑 发表于 2026-7-2 23:57

梦江南 发表于 2026-7-2 20:05
谢谢黑黑老师回复,看看也是学习。

对,学无止境

霜染枫丹 发表于 2026-7-3 01:02

马老师晚上好!您的这个帖子是我的绝缘体,我走不进去是正常的{:4_173:}。那就键盘支持,祝您安好!{:4_204:}{:4_190:}

马黑黑 发表于 2026-7-3 13:42

霜染枫丹 发表于 2026-7-3 01:02
马老师晚上好!您的这个帖子是我的绝缘体,我走不进去是正常的。那就键盘支持,祝您安好!{:4_204 ...

{:4_190:}

红影 发表于 2026-7-3 21:01

马黑黑 发表于 2026-7-2 23:57
嗯,这事很难理解的知识

努力学习中{:4_187:}

马黑黑 发表于 2026-7-3 22:49

红影 发表于 2026-7-3 21:01
努力学习中

{:4_190:}
页: [1]
查看完整版本: 初识 Selection 对象