页面文字标注

实现效果:











标注功能实现思路一般有两种:

一、后端会把数据分两部分存储,①文章区纯文字②包含HTML结构的字符串

前端请求数据时直接返给前台,前端直接展示。

我们目前采用该思路,实现的还相对容易些

二、后端存储大的集合,包含文章源文字与标注信息集合(多标注点的起始点、结束点),前端取到该信息进行再进行处理回显与操作,该思路下也会衍生出很多问题,例如一旦插入span标签,会改变源文字长度,标注所记录的起始点、结束点信息会发生错误等

页面上文字标注过程中遇到几个问题:

一、添加标注(一个滑动选区的标注)







①当鼠标在文章中滑动选择时,选择区可用window.getSelection()获取,得到一个选区对象selObj

②selObj.toString()可得到鼠标选择的哪些文字

③selObj.getRangeAt(0)可得到range对象

④range.surroundContents(ele)即可把选择的包裹

二、移除

移除一个标注(title放入了要标注文字,然后用之直接替代所在DOM)







三、不能在文章区域外标注,只能在文章区域标注







四、标注同类高亮







选择文档区所有子元素,进行遍历,对未标注的同类进行替换操作,对已经标注的获取outerHTML,拼接成总HTML字符串,替换掉文章区DOM

五、标注源取消标注,同类高亮也跟随取消

(1)单独实现一、二功能时,添加移除是正常的,但经过四功能替换文章区DOM,移除会有问题

①把移除函数放在最外层DOM树上,点击某个按钮时,获取该按钮区域,再进行相关操作

(2)点击某一个标注的删除按钮时,其他相同标注也随之删除

①获取点击点目标,获取到tite。

let pText=e.target.parentElement.title

②获取容器下所有的子节点

let dom=document.getElementById('docText').childNodes

③对子节点集合进行遍历,经筛选过滤,判断title相等的,对该节点用title文字进行原地替换,以实现删除标注后的标签

for(let i=0;i<dom.length;i++){

          //只对标注的节点操作

          if(dom[i].textContent.indexOf('*]x') > -1){

            if(dom[i].title === pText){

              dom[i].replaceWith(pText)

            }

          }

}

六、标注回显

后台会把数据分两部分存储,①文章区纯文字②包含HTML结构的字符串

前台请求数据时直接返给前台

关键代码:

methods: {
    toTag(value,index){
      let that = this
      let domNode = document.getElementById('docText')
      //判断选择区域是否在docText中
      let has=window.getSelection().containsNode(domNode, true)
      if(has){//判断鼠标滑动区域是否在文档区域内
        let str = value.proxy
        let selObj=window.getSelection()
        let txtString=selObj.toString()
        let spanTxt = str.slice(0,2) + txtString + str.slice(2)
        // console.log(spanTxt)
        if(txtString){
          let range=selObj.getRangeAt(0)
          // console.log(range)
          let ele=document.createElement('span')
          let eleDel=document.createElement('span')
          ele.style.backgroundColor=value.btnBgColor
          ele.className='customTag'
          ele.title=txtString
          eleDel.className='del_bt'
          eleDel.textContent='x'
          // eleDel.onclick=()=>that.toDel(ele)
          range.surroundContents(ele)
          let s='<span class="tagText">'+ spanTxt +'</span>'
          ele.innerHTML=s
          ele.appendChild(eleDel)
          //文章标注(所标选文字同类高亮)
          let dom=document.getElementById('docText').childNodes
          console.log(dom)
          let pingStr=''
          for(let i=0;i<dom.length;i++){
            //同类高亮
            //已经标注了的,排除掉。只对未标注的操作
            if(dom[i].textContent.indexOf('*]x') === -1){
              let paragraph=dom[i].textContent
              let reg=new RegExp(txtString,'g')
              let t=`<span class="customTag" title="${txtString}" style="background-color: rgb(167,173,177);"><span class="tagText">${spanTxt}</span><span class="del_bt">x</span></span>`
              let replacedTxt=paragraph.replace(reg,t)
              pingStr+=replacedTxt
              // dom[i].replaceWith(replacedTxt)
              // console.log(dom[i].textContent)
            }else{
              pingStr+=dom[i].outerHTML
              // console.log(dom[i].outerHTML)
            }
          }
          // console.log(pingStr)
          document.getElementById('docText').innerHTML=pingStr
          window.getSelection().removeAllRanges()
        }
      }else{
        this.$modal.msgError("请在文档区域进行标记")
      }
    },
    //点击删除按钮时 删除全部同类
    toDel(e){
      if(e.target.className==='del_bt'){
        console.log(e.target.parentElement.title)
        let pText=e.target.parentElement.title
        console.log(document.getElementById('docText').childNodes)
        let dom=document.getElementById('docText').childNodes
        for(let i=0;i<dom.length;i++){
          //只对标注的操作
          if(dom[i].textContent.indexOf('*]x') > -1){
            if(dom[i].title === pText){
              dom[i].replaceWith(pText)
            }
          }
        }

      }
    }
  }

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值