【问题标题】:Change Text Color When a Word is Clicked单击单词时更改文本颜色
【发布时间】:2021-05-30 22:37:11
【问题描述】:

我正在尝试创建一个应用程序,用户可以通过该应用程序在单击(或双击)特定单词时突出显示该特定单词。也就是说,用户可以点击文章中任何段落中的任何单词,并通过更改其背景颜色或更改其字体颜色来突出显示它。

不过,我遇到了麻烦,请弄清楚如何做到这一点。我不想突出显示整个段落,也不想将每个单词包装在一个独特的组件或 html 标记中。我基本上想要的是整篇文章的包装组件,它只记录被点击的特定单词,然后让我决定我想要更改该单词的哪些 css 属性(例如背景颜色或文本颜色)。

但我不知道该怎么做。有没有一个图书馆已经这样做了。如果没有,我怎样才能将文章作为一个整体包装,但可以访问被点击的单数词?

不管怎样,我正在使用 React 创建应用程序。

【问题讨论】:

  • 请访问help center,使用tour查看内容和How to Ask。做一些研究,搜索关于SO的相关主题;如果您遇到困难,请发布您尝试的minimal reproducible example,并使用[<>] sn-p 编辑器记录输入和预期输出。
  • 您对您想使用的“词”有什么定义吗?它只是在它之前和之后带有空格/换行符/标点符号的东西还是...?
  • 这可能有助于 [link]stackoverflow.com/questions/7563169/…,因为它避免了数百个(大部分未使用的)跨度使您的 HTML 混乱。但是除了更改颜色或突出显示之外,您还想做什么?单词是否会变得不突出/可以同时突出显示多个单词吗?

标签: javascript html css reactjs react-component


【解决方案1】:

您可以使用此方法访问页面中的选定文本:

window.getSelection()

现在我们可以编辑页面中的任何选定文本,如下所示:

window.getSelection().anchorNode.parentElement.innerHTML =
window.getSelection().anchorNode.parentElement.innerHTML.replace(
  window.getSelection().toString() ,
    "<b>" +
    window.getSelection().toString() +
    "</b>"
  )

此代码将所选文本加粗以更改颜色或高亮显示,您可以试试这个:

  window.getSelection().anchorNode.parentElement.innerHTML =
    window.getSelection().anchorNode.parentElement.innerHTML.replace(
      window.getSelection().toString() ,
        "<span style='color:red;'>" +
        window.getSelection().toString() +
        "</span>"
      )

希望有用:)

【讨论】:

    【解决方案2】:

    不使用任何库,你可以这样,按单词分割,点击后应用一些样式

    <html>
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <title>Click a word in the paragraph and highlight it.</title>
        <script src="https://code.jquery.com/jquery-git.js"></script>
    </head>
    
    <body>
        <p id="paragraph">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
        </p>
        <script>
            $( document ).ready(
                function() {
                    const words = $("#paragraph").first().text().split( /\s+/ );
                    const text = words.join( "</span> <span>" );
                    $( "#paragraph" ).first().html( "<span>" + text + "</span>" );
                    $( "span" ).on( "click", function() {
                    $( this ).css( "background-color", "red" );
                    });
                }
            )
        </script>
    </body>
    
    </html>

    【讨论】:

      【解决方案3】:

      如果我们从 Detect which word has been clicked on within a text 中获取想法,我们可以将一个单词的所有实例替换为包含在 span 中的单词,例如,突出显示。

      此代码仅使用空格作为单词分隔符,显然在生产中需要使用更广泛的单词定义。它还突出显示点击单词的所有出现 - 不清楚这是否是必需的 - 并删除任何现有的突出显示。同样在生产中,可能需要不同类型的突出显示,具体取决于单击的特定单词,因此这只是开始:

      <head>
      <style>
      .highlight {
        background-color: yellow;
      }
      </style>
      </head>
      <body>
      <div class="clickable">
      <p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr,  sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr,  sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
      
      </p><p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.
      
      Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.
      
      Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.
      
      </p><p>Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.
      </p>
      </div>
      <script>
          let clickable = document.querySelector('.clickable');
          
          clickable.addEventListener('click',function (e) {
              
              let sel = window.getSelection();
              let range = sel.getRangeAt(0);
              let node = sel.anchorNode;
              //NOTE at the moment we are only looking at space terminating a word. Need probably to look for all non alphabetic characters (e.g. punctuation)
              while ((range.toString().indexOf(' ') != 0) && (range.startOffset > 0)) { //check we aren't at the start of the clickable element             
                  range.setStart(node,(range.startOffset -1));
              }
              range.setStart(node, range.startOffset +1);
               
              do {
                 range.setEnd(node,range.endOffset + 1);
              } while(range.toString().indexOf(' ') == -1 && range.toString().trim() != '');
              
              let word = range.toString().trim();
              
              clickeds = clickable.querySelectorAll('.highlight');
              for (let j=0; j < clickeds.length; j++) {
                  clickeds[j].outerHTML = clickeds[j].innerHTML;// remove span for hightlighting
              }
              clickable.innerHTML = clickable.innerHTML.replaceAll(word, '<span class="highlight">' + word + '</span>' );
             });
      
      </script>
      </body>

      【讨论】:

        【解决方案4】:

        出于我的目的,css 伪选择器 ::selection 完成了这项工作。它允许我更改单击的任何单词(或突出显示的任何单词组)的背景或文本颜色。

        唯一的缺点是它不允许我保持一直是clicked 的状态——所以我不能点击多个单词并让它们都改变颜色。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多