成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

選中鼠標(biāo)附近的文字

shuibo / 656人閱讀

摘要:它的原理是深度優(yōu)先遞歸遍歷這個(gè)元素以及其子元素,通過不斷試探選中區(qū)域,并與鼠標(biāo)座標(biāo)對(duì)比來定位確切位置。原理現(xiàn)在總結(jié)一下原理通過獲得鼠標(biāo)所指最接近的元素以及文本位置。驗(yàn)證鼠標(biāo)此時(shí)在單詞區(qū)域范圍中。

最近終于抽空給 Saladict 實(shí)現(xiàn)了鼠標(biāo)懸浮取詞功能,使用了較為簡潔的實(shí)現(xiàn)方式,這里分享一下原理以及坑的處理。

初嘗試

這個(gè)需求其實(shí)很早就被人提 issue 了,當(dāng)時(shí)做了一番搜索,最后嘗試了 document.caretPositionFromPoint / document.caretRangeFromPoint ,效果不太理想。

如果看 mdn 給的例子,就會(huì)發(fā)現(xiàn),它是遍歷每個(gè)元素添加事件的。這么做的原因是當(dāng)使用這個(gè)方法的時(shí)候,如果鼠標(biāo)指向元素空白的地方,它會(huì)就近取位置。所以例子通過給粒度更細(xì)的元素綁定來避免這個(gè)問題。然而實(shí)際上這么做還是不足夠的,一個(gè)段落末行也許只有幾個(gè)字符,這時(shí)空出接近一行,也會(huì)有上面的問題。

所以當(dāng)時(shí)就擱置了這個(gè)功能。

靈感

直到最近,看到一個(gè)同類的開源劃詞翻譯擴(kuò)展 FairyDict 實(shí)現(xiàn)了取詞功能,遍觀摩了一番源碼。

它的原理是深度優(yōu)先遞歸遍歷這個(gè)元素以及其子元素,通過不斷試探選中區(qū)域,并與鼠標(biāo)座標(biāo)對(duì)比來定位確切位置。

有沒有發(fā)現(xiàn)問題,這個(gè)遍歷過程不正是上面 document.caretPositionFromPoint 干的事么,那么我們只需要最后量一下鼠標(biāo)是否在取詞范圍中即可。

原理

現(xiàn)在總結(jié)一下原理:

通過 document.caretPositionFromPoint 獲得鼠標(biāo)所指最接近的元素以及文本位置 offset。

找出 offset 最接近的單詞。

通過 Range 獲得部分文本(單詞)的尺寸和座標(biāo)。

驗(yàn)證鼠標(biāo)此時(shí)在單詞區(qū)域范圍中。

選中這個(gè)單詞。Selection 支持直接添加 Range 。

實(shí)現(xiàn)

按原理來實(shí)現(xiàn)就很簡單了。本文上按 alt 可體驗(yàn)取詞效果。

/**
 * @param {MouseEvent} e
 * @returns {void}
 */
function selectCursorWord (e) {
  const x = e.clientX
  const y = e.clientY

  let offsetNode
  let offset

  const sel = window.getSelection()
  sel.removeAllRanges()

  if (document["caretPositionFromPoint"]) {
    const pos = document["caretPositionFromPoint"](x, y)
    if (!pos) { return }
    offsetNode = pos.offsetNode
    offset = pos.offset
  } else if (document["caretRangeFromPoint"]) {
    const pos = document["caretRangeFromPoint"](x, y)
    if (!pos) { return }
    offsetNode = pos.startContainer
    offset = pos.startOffset
  } else {
    return
  }

  if (offsetNode.nodeType === Node.TEXT_NODE) {
    const textNode = offsetNode
    const content = textNode.data
    const head = (content.slice(0, offset).match(/[-_a-z]+$/i) || [""])[0]
    const tail = (content.slice(offset).match(/^([-_a-z]+|[u4e00-u9fa5])/i) || [""])[0]
    if (head.length <= 0 && tail.length <= 0) {
      return
    }

    const range = document.createRange()
    range.setStart(textNode, offset - head.length)
    range.setEnd(textNode, offset + tail.length)
    const rangeRect = range.getBoundingClientRect()

    if (rangeRect.left <= x &&
        rangeRect.right >= x &&
        rangeRect.top <= y &&
        rangeRect.bottom >= y
    ) {
      sel.addRange(range)
    }

    range.detach()
  }
}
交互

最后,如果要提供功能開關(guān)或者設(shè)置不同按鍵的話,簡單的處理可以參考 FairyDict 讓事件處理空轉(zhuǎn)。但對(duì)于 mousemove 這類比較頻繁的事件,在關(guān)閉的時(shí)候取消事件監(jiān)聽可能更好一些。在 Saladict 中甚至將“面板被釘住”跟“普通情況”分開為不同的模式,這里借助 RxJS 來處理復(fù)雜的邏輯,可參考源碼。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95615.html

相關(guān)文章

  • 宇宙最強(qiáng)vscode教程(基礎(chǔ)篇)

    摘要:在命令面板中你可以輸入命令進(jìn)行搜索中英文都可以,然后執(zhí)行。命名面板中可以執(zhí)行各種命令,包括編輯器自帶的功能和插件提供的功能。 本文主要介紹vscode在工作中常用的快捷鍵及插件,目標(biāo)在于提高工作效率本文的快捷鍵是基于mac的,windows下的快捷鍵放在括號(hào)里 Cmd+Shift+P(win Ctrl+Shift+P) [TOC] 零、快速入門 有經(jīng)驗(yàn)的可以跳過快速入門或者大致瀏覽一...

    Jason_Geng 評(píng)論0 收藏0
  • 原生JS寫一個(gè)功能強(qiáng)大編輯器

    摘要:主要采用了原生與調(diào)用結(jié)合的功能實(shí)現(xiàn)功能。所以根據(jù)這種方法,讀者可以根據(jù)自己的需求添加更多的功能,比如在編輯框里面插入一個(gè)可以點(diǎn)擊的標(biāo)簽或者添加一個(gè)代碼塊希望能讀到此文章的讀者,能在下方一起交流,更希望大佬提出錯(cuò)誤,謝謝地址 因?yàn)橐粋€(gè)同學(xué),要做一個(gè)能加入圖片的留言板功能,類型與QQ空間留言板和百度貼吧發(fā)帖的那種形式,同時(shí)在網(wǎng)上找了找發(fā)生網(wǎng)上對(duì)這方面的交流很少,所以發(fā)表這篇文章拋磚引玉,希...

    luck 評(píng)論0 收藏0
  • 原生JS寫一個(gè)功能強(qiáng)大編輯器

    摘要:主要采用了原生與調(diào)用結(jié)合的功能實(shí)現(xiàn)功能。所以根據(jù)這種方法,讀者可以根據(jù)自己的需求添加更多的功能,比如在編輯框里面插入一個(gè)可以點(diǎn)擊的標(biāo)簽或者添加一個(gè)代碼塊希望能讀到此文章的讀者,能在下方一起交流,更希望大佬提出錯(cuò)誤,謝謝地址 因?yàn)橐粋€(gè)同學(xué),要做一個(gè)能加入圖片的留言板功能,類型與QQ空間留言板和百度貼吧發(fā)帖的那種形式,同時(shí)在網(wǎng)上找了找發(fā)生網(wǎng)上對(duì)這方面的交流很少,所以發(fā)表這篇文章拋磚引玉,希...

    王晗 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<