在 svelte 代码中添加点击功能时出现问题。我正在尝试在前端实现特定文本的注释

问题描述 投票:0回答:1

我目前正在致力于在 Svelte 框架中实现注释。您可以在下面的代码中看到我正在使用的数据结构。可视化工作完美,内容样式基于字符索引。然而,我在为用户交互添加“on:click”功能时面临着挑战。我的困难在于整个样式是在 JavaScript 函数中定义的,我需要循环注释,考虑它们的开始和结束索引。

非常感谢您帮助添加“on:click”功能,以便我可以集成其他功能,例如在用户与注释交互时修改或删除注释。这种方法看起来合适吗,或者有什么错误吗?非常感谢您的帮助。

<script>
  // @ts-nocheck
    
  let colorAnnotation = '#ff798090';
  let colorAnnotationText = '#ee456789';
    
  let annotatedData = {
    'text': `
    The sun hung low in the sky, casting long shadows across the quiet street. The sound of children playing echoed in the distance, and a gentle breeze rustled the leaves of the trees. It was a peaceful evening, perfect for a leisurely walk and some quiet reflection.
    
    As I strolled down the cobblestone path, the aroma of freshly baked bread wafted from a nearby bakery, tempting my senses. I couldn't resist stepping inside, where warm smiles greeted me, and I indulged in a warm baguette, still soft from the oven. With each bite, I felt a sense of contentment wash over me, savoring the simple pleasures of life on this serene evening.
    `,
    'annotations': [
        {
            'label': 'action',
            'start_offset': 23,
            'end_offset': 52,
        },
        {
            'label': 'comedy',
            'start_offset': 177,
            'end_offset': 206,
        },
        {
            'label': 'white',
            'start_offset': 272,
            'end_offset': 308,
        },
        {
            'label': 'location',
            'start_offset': 132,
            'end_offset': 166,
        },
        {
            'label': 'description',
            'start_offset': 313,
            'end_offset': 348,
        }
    ]
  };
    
  let formattedText = formatText(annotatedData.text, annotatedData.annotations);
    
  let isPopupMenuVisible = false;
  let popupMenuX = 0;
  let popupMenuY = 0;
    
  function popUpMenu(label, x, y) {
    // Here you can implement logic to show a pop-up menu
    // For this example, we'll just alert the label
    alert(`You clicked on: ${label}`);
    isPopupMenuVisible = true;
    popupMenuX = x;
    popupMenuY = y;
  }
    
  function formatText(text, annotations) {
    // Sort annotations by start_offset in ascending order
    annotations.sort((a, b) => a.start_offset - b.start_offset);

    let result = [];
    let lastIndex = 0;

    annotations.forEach(annotation => {
      const start = annotation.start_offset;
      const end = annotation.end_offset;

      // Text before the annotation
      result.push(text.substring(lastIndex, start));

      // Span for the annotation with Svelte on:click handler
      result.push(`
        <span style="background-color:${colorAnnotation}; cursor: pointer" on:click={() => popUpMenu('${annotation.label}', event.clientX, event.clientY)}
          >
          <span style="position:relative; background-color:white; color: ${colorAnnotationText};">${annotation.label}</span>
          ${text.substring(start, end)}
        </span>
      `);

      lastIndex = end;
    });

    // Text after the last annotation
    result.push(text.substring(lastIndex));

    return result.join('');
  }</script>
    
<div>
  {@html formattedText}
</div>
    
<div class="popup-menu" style="left:{popupMenuX}px; top:{popupMenuY}px; display: {isPopupMenuVisible ? 'block' : 'none'}">
    <!-- Add your pop-up menu content here -->
  <button on:click={() => isPopupMenuVisible = false}>Close</button>
</div>
    
<style>
  /* Define your styles here */
  .popup-menu {
    position: absolute;
    background-color: white;
    border: 1px solid #ccc;
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
    z-index: 999;
    padding: 10px;
  }
</style>

javascript html onclick svelte
1个回答
0
投票

您不能在动态插入的 HTML 中使用

on:event
,这是需要编译的 Svelte 特定语法。

使用 Svelte 标记/单独的组件,或使用事件冒泡来处理 Svelte 中静态定义的父元素上的所有注释事件。

如果您想使用标记/组件,您可以将数据预处理为标记,然后使用

#each
来渲染它们,而不是使用
@html
。例如

{#each tokens as token}
  {#if token.type == 'text'}
    {token.text}
  {:else if token.type == 'annotation'}
    <!-- Use button, otherwise accessibility sucks -->
    <button type="button" class="annotation"
            on:click={() => onAnnotationClick(token)}>
      {token.text}
    </button>
  ...
{/each}

对于活动委托:

<div on:click={onWrapperClick}>
  {@html formattedText}
</div>
// when adding annotations
result.push(`
  <button type="button" ... data-annotation-id="${...}">
    ${text.substring(start, end)}
  </button>
`);

// handle clicks
function onWrapperClick(e) {
  const annotation = e.target.closest('[data-annotation-id]');
  if (!annotation)
    return;

  const id = annotation.dataset.annotationId;
  // [do stuff]
}

要删除默认按钮样式,请先取消所有设置:

.annotation { all: unset; }
.annotation:focus-visible { outline: auto } /* restore focus display */
© www.soinside.com 2019 - 2024. All rights reserved.