如何在文本区域(坐标)角度中获取位置突出显示的文本?

Posted

技术标签:

【中文标题】如何在文本区域(坐标)角度中获取位置突出显示的文本?【英文标题】:How to get postition highlighted text in textarea (coords) angular? 【发布时间】:2022-01-23 10:05:17 【问题描述】:

我想在 textarea 中获得类似的东西。我无法将 textarea 更改为 contentaditable div。如何获取所选文本的位置?我需要这个从上面显示这个弹出窗口

【问题讨论】:

【参考方案1】:

您应该能够轻松地将其转换为角度代码。 这是您需要做的基本工作,它没有经过全面测试,但它几乎可以工作。

const textarea = document.getElementById('text')
const result = document.getElementById('selected')
const tooltip = document.getElementById('tooltip')

const cols = document.getElementById('text').cols;
const width = document.getElementById('text').clientWidth;
const height = window.getComputedStyle(textarea).lineHeight;


textarea.onclick = function getSelection() 
  const pos = 
    top: textarea.offsetTop,
    left: textarea.offsetLeft,
  ;
  result.textContent = `$textarea.selectionStart, $textarea.selectionEnd`;
  let selection
  if (textarea.selectionStart) 
    selection = textarea.selectionStart;
   else if (document.selection) 
    textarea.focus();
    const r = document.selection.createRange();
    if (r == null) 
      selection = 0;
    
    let re = textarea.createTextRange();
    let rc = re.duplicate();
    re.moveToBookmark(r.getBookmark());
    rc.setEndPoint('EndToStart', re);
    selection = rc.text.length;
   else 
    selection = 0
  
  const row = Math.floor((selection - 1) / cols);
  const col = (selection - (row * cols));
  const x = Math.floor((col * (width / cols)));
  const y = (parseInt(height) * row);
  tooltip.innerhtml = "<b>row: " + row + "<br>columns" + col + "<br>width: " + width + "</b>";
  tooltip.style.top = `$pos.top+ypx`;
  tooltip.style.left = `$pos.left+x+10px`;
textarea 
  height: 80px;
  line-height: 12px;
  overflow-y: scroll;
  display: block;


#tooltip 
  position: absolute;
  background:red;
  color: white;
<textarea id="text">Lopsum</textarea>
<span id="tooltip"></span>
<span id="selected"></span>

【讨论】:

知道索引如何帮助我显示弹出窗口?我想知道选区所在的高度和宽度 宽度:每次151 那是文本区域的宽度,它是静态的。请先检查代码。 但我需要在 px 中定位所选文本 x,y定位应该等于tooltip.style.left, tooltip.style.top【参考方案2】:

我想的唯一方法是创建文本区域的副本(非常类似于 SO,(欧文开尔文的回应)关于文本区域中的高亮词

由于我们只需要位置,我们可以拆分“texarea”和“background”。此外,使用 another SO 中的 Yurzui 响应,我们可以控制何时调整文本区域的大小

我们可以想象一个 .html 之类的

<div class="container">
    <div
      #backdrop
      class="backdrop"
      [style.width.px]="textWidth"
      [style.height.px]="textHeight"
    >
      <div
        class="highlights"
        [innerHTML]="sanitizer.bypassSecurityTrustHtml(highlightedText)"
      ></div>
    </div>
  </div>
  <textarea
    #textarea
    spellcheck="false"
    (resize)="rect = null;"
    (select)="applyHighlights(textarea.value)"
    (mousedown)="mouseDown()"
    (blur)="rect = null"
    [ngModel]="textValue"
    (ngModelChange)="textValue = $event; applyHighlights(textarea.value)"
    (scroll)="handleScroll(); applyHighlights(textarea.value)"
  ></textarea>

<div
  class="tooltip"
  *ngIf="rect"
  [style.top.px]="rect.y"
  [style.left.px]="rect.x"
></div>

看到“文本”被隐藏了,因为我们有一个像这样的 div 容器

.container 
  overflow:hidden;
  width:0;
  height:0;

我们使“text”的尺寸由两个变量“textWidth”和“textHeight”决定

代码是

  ngOnInit() 
    this.resize();
  

  resize() 
    const event = 
      width: this.$textarea.nativeElement.getBoundingClientRect().width,
      height: this.$textarea.nativeElement.getBoundingClientRect().height,
    ;
    this.textWidth = event.width;
    this.textHeight = event.height;
  
  mouseDown() 
    setTimeout(() => 
      const start = this.$textarea.nativeElement.selectionStart;
      const end = this.$textarea.nativeElement.selectionEnd;
      if (start == end) this.rect = null;
    );
  
  applyHighlights(text: string) 
    if (text) 
      let start = this.$textarea.nativeElement.selectionStart;
      let end = this.$textarea.nativeElement.selectionEnd;
      if (start == end) this.highlightedText = text;
      else 
        const selected = text.substr(start, end - start);
        this.toolTipText=this.getTooltipText(selected)
        this.highlightedText =
          text.substr(0, start) +
          "<span id='mark'>" +
          selected +
          '</span>' +
          text.substr(end);
        this.resize();
        setTimeout(() => 
          const recArea = this.$textarea.nativeElement.getBoundingClientRect();
          const recText = this.$backdrop.nativeElement.getBoundingClientRect();

          const rect = document.getElementById('mark').getBoundingClientRect();
          rect.y += window.scrollY;
          rect.x+=rect.width/2
          this.rect = rect.y - window.scrollY < recArea.y ? null : rect;
        );
      
    

  
  handleScroll() 
    var scrollTop = this.$textarea.nativeElement.scrollTop;
    this.$backdrop.nativeElement.scrollTop = scrollTop;

    var scrollLeft = this.$textarea.nativeElement.scrollLeft;
    this.$backdrop.nativeElement.scrollLeft = scrollLeft;
  

我在stackblitz 中放入了一个自定义表单组件(原因是欧文为我做了这个工作

【讨论】:

以上是关于如何在文本区域(坐标)角度中获取位置突出显示的文本?的主要内容,如果未能解决你的问题,请参考以下文章

如何以角度突出显示文本区域中的文本?

文本区域中的光标位置(字符索引,不是 x/y 坐标)

在文本区域中突出显示简单的 Javascript?

如何在文本区域的当前插入符号位置插入文本

如何在文本区域中显示文本的结尾

如何在文本区域的末尾设置光标?