SOURCE

console 命令行工具 X clear

                    
>
console
new Vue({
    el: '#app',
    data: {
        list: [
            {
                id: '151A5A51',
                range: {
                    id: '151A5A51',
                    text: '我不禁头涔涔而泪潸潸了。',
                    start: {
                        path: [7, 4],
                        offset: 59,
                        text: '我不禁头'
                    },
                    end: {
                        path: [7, 8],
                        offset: 2,
                        text: '了。'
                    },
                    config: {
                        rect: {
                            fill: 'rgba(255, 170, 0, 0.2)',
                            visible: true
                        },
                        line: {
                            stroke: 'rgba(255, 170, 0, 1)',
                            strokeWidth: 2,
                            visible: true
                        }
                    }
                },
                text: '测试评论'
            }
        ],
        range: null,
        highlighter: null,
        style: {
            top: 0,
            left: 0,
            display: 'none'
        },
        active: ''
    },
    mounted() {
        const container = document.getElementById('container')
        // console.log(39,CanvasHighlighter)
        this.highlighter = new CanvasHighlighter(container)
        this.highlighter.renderRanges(this.list.map(item => item.range))
        this.active = this.list[0].id

        document.addEventListener('click', event => {
            // geRangeIdByPointer
            const id = this.highlighter.geRangeIdByPointer(event.clientX, event.clientY)
            let range = this.highlighter.getRange(this.active)
            if (range) {
                range.config.rect.visible = false
                this.highlighter.updateRange(range)
            }
            this.active = ''
            if (id) {
                this.active = id
                const range = this.highlighter.getRange(id)
                range.config.rect.visible = true
                this.highlighter.updateRange(range)
            }
        })

        container.addEventListener('mouseup', () => {
            this.range = this.highlighter.getSelectionRange()
            console.log('mouseup')
            if (this.range) {
                const { end } = this.highlighter.getSelectionPosition()
                this.style = {
                    top: (end.y - 35) + 'px',
                    left: (end.x + 4) + 'px',
                    display: 'inlin-block'
                }
            }
        })


    },
    methods: {
        activeStyle(data) {
            return data.row.id === this.active ? { background: '#ecf5ff' } : {}
        },
        click() {
            if (this.range) {
                console.log(91,this.$prompt)
                this.$prompt('请输入评论内容', '评论').then(({ value }) => {
                    console.log(93)
                    this.list.push({
                        id: this.range.id,
                        range: this.range,
                        text: value
                    })
                    // 自定义隐藏矩形,只显示下划线
                    this.range.config.rect.visible = false
                    // 高亮选中区域
                    this.highlighter.addRange(this.range)
                }).catch((err) => { throw (err) })
            }
            this.style.display = 'none'
        },
        handleDelete(id) {
            const index = this.list.findIndex(i => i.id === id)
            this.list.splice(index, 1)
            this.highlighter.deleteRange(id)
        }
    }
})

<a href="https://juejin.cn/post/7140078451205079054#heading-9">纯 JS 实现语雀的划词高亮功能 掘金 </a>
<br>
<br>
<a href="https://dlillard0.github.io/canvas-highlighter/yuque.html" target="__self"> 纯 JS 实现语雀的划词高亮功能 demo</a>
<p class="tip">尝试在下方区域进行划词评论  {{active}}</p>
  <p class="tip">尝试点击划词区域内容</p>
  <section>
    <div id="container">
      <p style="text-align: center;"><span style="font-size: 22px;font-weight: bold;">匆匆</span></p>
      <p style="text-align: center;"><span style="font-weight: bold;">朱自清</span></p>
      <p>
        燕子去了,有再来的时候杨柳枯了,有再青的时候桃花谢了,有再开的时候。但是聪明的你告诉我,我们的日子为什么一去不复返呢?是有人偷了他 们罢:那是谁?又藏在何处呢?是他们自己逃走了罢如今又到了哪里呢?
      </p>
      <p>
        我不知道他们给了我多少日子,但我的手<span style="font-size: 20px; color: #F56C6C;">确乎</span>是渐渐<span style="font-size: 20px; color: #F56C6C;">空虚</span>了。在默默里算着,八千多日子已经从我手中溜去,像针尖上一滴水滴在大海里,我的日子滴在时间的流里,没有声音,也没有影子。我不禁头<span style="font-size: 20px; color: #F56C6C;">涔涔</span>而泪<span style="font-size: 20px; color: #F56C6C;">潸潸</span>了。去的尽管去了,来的尽管来着,去来的中间,又怎样地匆匆呢?
      </p>
      <p>
        早上我起来的时候,小屋里射进两三方斜斜的太阳。太阳他有脚啊,轻轻悄悄地挪移了,我也茫茫然跟着旋转。于是洗手的时候,日子从水盆里过去,吃饭的时候,日子从饭碗里过去,默默时,便从凝然的双眼前过去。我觉察他去的匆匆了,伸出手遮挽时,他又从遮挽着的手边过去。
      </p>
      <p>
        天黑时,我躺在床上,他便<span style="font-size: 20px; color: #F56C6C;">伶伶俐俐</span>地从我身上跨过,从我脚边飞去了。等我睁开眼和太阳再见,这算又溜走了一日。我掩着面叹息。但是新来的日子的影儿又开始在叹息里闪过了。在逃去如飞的日子里,在千门万户的世界里的我能做些什么呢?
      </p>
      <p>
        只有<span style="font-size: 20px; color: #F56C6C;">徘徊罢了</span>,只有匆匆罢了,在八千多日的匆匆里,除徘徊外,又剩些什么呢?过去的日子如轻烟,被微风吹散了,如薄雾,被初阳蒸融了。我留着些什么痕迹呢?我何曾留着像<span style="font-size: 20px; color: #F56C6C;">游丝</span>样的痕迹呢?
      </p>
      <p>
        我赤裸裸来到这世界,转眼间也将赤裸裸的回去罢?但不能平的,为什么偏要白白走这一遭啊?你聪明的,告诉我,我们的日子为什么一去不复返呢?
      </p>
    </div>
    <button class="btn btn-primary btn-sm action" style="position: absolute;top:10px;left:10px; display:inline-block;" type="button">评论</button>
  </section>


   <div id="app">
    <el-table
      :data="list"
      style="width: 100%"
      :row-style="activeStyle">
      <el-table-column
        prop="range.text"
        label="划词内容">
      </el-table-column>
      <el-table-column
        prop="text"
        label="评论内容">
      </el-table-column>
      <el-table-column
        label="操作">
        <template slot-scope="scope">
          <el-button type="danger" size="mini" @click="handleDelete(scope.row.id)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-button ref="btn" type="primary" size="mini" :style="style" @click="click">评论</el-button>
  </div>

  body {
      padding: 20px;
      background-color: white;
    }
    .tip {
      font-size: 20px;
      color: #409EFF;
    }
    #container {
      padding: 16px;
      border: 1px solid #999;
      border-radius: 4px;
      line-height: 1.8;
    }
    #app > .el-button {
      position: absolute;
      display: none;
    }

本项目引用的自定义外部资源