textarea A prompt box appears following the cursor position (similar to input method function)

Realization ideas

You can use e.target.selectionStart to know the position of the cursor, but it doesn't work when facing enter line breaks and spaces.
And e.target.selectionStart can only know the position in the text string, what we need is the position from the border, so that we can assign values ​​to the left and top of the prompt box.

So the idea is to use an identical div in the same position of the textarea for visibility hidden.
Insert a span tag at the cursor position and get the offsetTop and offsetLeft of the span;

Implementation code

html part:

<div class="textarea-div">
         <!--隐藏在背后的div用来获取位置-->
          <div style="position: absolute; visibility:hidden;width: 100%; height: 100%" v-html="hiddenText"></div>
          <!--真正的输入输入框-->
          <textarea ref="textArea" class="textarea" v-model="text" placeholder="请输入一段文字" @keyup="keyupEvent($event)" ></textarea>
           <!--悬浮的提示框-->
          <div class="recomand-pop-over" :style="recomandPop">
          </div>

js:

// $event 传进函数
// 用<pre></pre> 标签可以解决 换行 与 空格
 dosomething(e){
    
    
   if (e.target.selectionStart === e.target.textLength) {
    
    
       // 表示光标在正常的位置, 没有往回点击
        this.hiddenText = `<pre>${
      
      e.target.value}<span class="slot-span">1</span></pre>`;
      } else {
    
    
      // 如果光标点回到了之前位置的, 需要使用e.target.selectionStart, 将span插入进去
        this.startPos = e.target.selectionStart;
        this.endPos = e.target.selectionEnd;
        const originalStr = e.target.value;
        const newStr = `${
      
      originalStr.substring(0, this.startPos)}<span class="slot-span">1</span>${
      
      originalStr.substring(this.endPos, originalStr.length)}`;
        this.hiddenText = `<pre>${
      
      newStr}</pre>`;
      }
      this.$nextTick(() => {
    
    
        const MARK_SPAN = document.querySelector('.slot-span');
        this.recomandPop = {
    
     //具体细节可以再加减 10 px之类的。
          left: `${
      
      MARK_SPAN.offsetLeft}px`,
          top: `${
      
      MARK_SPAN.offsetTop}px`,
        };
        this.$forceUpdate();
      });
 }
      

Guess you like

Origin blog.csdn.net/Beth__hui/article/details/106694301