You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue组合式API中创建自定义HTML的DynamicMarker及添加远程用户标记

Ace编辑器远程协作标记实现方案

针对你基于Vue组合式API和Ace编辑器的场景,以下是两个问题的具体实现步骤:

1. 创建带自定义HTML的DynamicMarker

Ace的DynamicMarker需要继承自ace.Marker,通过重写render方法注入自定义HTML结构。在Vue组合式API中,可直接在<script setup>里定义这个自定义标记类:

// 自定义动态标记类,支持自定义HTML
class CustomRemoteMarker extends ace.Marker {
  constructor(range, htmlContent, cssClass) {
    super(range);
    this.htmlContent = htmlContent;
    this.cssClass = cssClass || 'remote-user-marker';
  }

  update(range) {
    this.range = range;
    this.session._signal('changeBackMarker');
  }

  render(session, layer, className) {
    const range = this.range;
    if (!range || !range.isValid()) return;

    const start = session.documentToScreenPosition(range.start.row, range.start.column);
    const end = session.documentToScreenPosition(range.end.row, range.end.column);

    // 创建自定义DOM元素
    const el = document.createElement('div');
    el.className = `${this.cssClass} ${className}`;
    el.innerHTML = this.htmlContent;
    
    // 设置元素位置(基于Ace的图层坐标)
    const top = layer.$getTop(start.row, 0);
    const left = layer.$padding + session.characterWidth * start.column;
    const height = session.lineHeight;
    const width = session.characterWidth * (end.column - start.column);

    el.style.position = 'absolute';
    el.style.top = `${top}px`;
    el.style.left = `${left}px`;
    el.style.height = `${height}px`;
    el.style.width = `${width}px`;
    el.style.pointerEvents = 'none'; // 避免干扰编辑器操作

    layer.element.appendChild(el);
  }
}

你可以按需修改htmlContent,比如展示远程用户的头像或用户名:<span class="user-avatar">👤</span><span class="user-name">User1</span>,同时在样式中定义.remote-user-marker的背景色、透明度等样式。

2. 添加远程用户标记到编辑器

在Vue的onMounted钩子中,编辑器初始化完成后,实例化自定义标记并通过addDynamicMarker添加到编辑器,同时处理远程用户位置更新逻辑:

<script setup>
import ace, { Range } from 'ace-builds'
import "ace-builds/webpack-resolver";
import 'ace-builds/src-noconflict/snippets/javascript'
import { reactive, ref, onMounted } from 'vue'

const ace_text_area = ref(null)
const props = defineProps({ value: String })
const state = reactive({
  aceEditor: null,
  value: "",
  remoteMarkers: new Map() // 存储远程用户标记,key为用户ID
})

// 自定义动态标记类(同上)
class CustomRemoteMarker extends ace.Marker {
  // ... 上述代码
}

onMounted(() => {
  state.value = props.value
  state.aceEditor = ace.edit(ace_text_area.value, { value: state.value });
  const editor = state.aceEditor;

  // 添加远程用户标记的方法
  const addRemoteUserMarker = (userId, range, userInfo) => {
    // 若用户已有标记,先移除
    if (state.remoteMarkers.has(userId)) {
      editor.removeMarker(state.remoteMarkers.get(userId));
    }
    // 创建自定义HTML内容
    const html = `<span style="color: #fff; font-size: 12px; background: #2563eb; padding: 2px 4px; border-radius: 3px;">${userInfo.name}</span>`;
    // 实例化标记
    const marker = new CustomRemoteMarker(range, html);
    // 添加到编辑器,第二个参数设为true表示在文本层上方渲染
    const markerId = editor.addDynamicMarker(marker, true);
    // 存储标记ID,方便后续更新或移除
    state.remoteMarkers.set(userId, markerId);
  }

  // 更新远程用户位置的方法
  const updateRemoteUserPosition = (userId, newRange) => {
    const markerId = state.remoteMarkers.get(userId);
    if (!markerId) return;
    // 获取标记实例并更新范围
    const marker = editor.getMarker(markerId);
    marker.update(newRange);
  }

  // 测试:添加一个远程用户标记(第2行第0列到第2行第5列)
  const testRange = new Range(1, 0, 1, 5);
  addRemoteUserMarker('user123', testRange, { name: 'RemoteUser' });

  // 实际场景中,通过WebSocket监听远程用户位置变化,调用updateRemoteUserPosition更新
})
</script>

<template>
  <div ref="ace_text_area" style="width: 100%; height: 500px;"></div>
</template>

<style scoped>
/* 自定义标记样式 */
.remote-user-marker {
  background-color: rgba(37, 99, 235, 0.2);
  border-left: 3px solid #2563eb;
}
</style>

关键说明:

  • addDynamicMarker的第二个参数设为true,确保标记在文本层上方渲染,不会被文本覆盖
  • 通过remoteMarkers Map存储用户ID和标记ID的映射,方便后续更新或移除远程用户的标记
  • 实际协作场景中,远程用户的位置信息需通过WebSocket等实时通信协议获取,调用updateRemoteUserPosition更新标记位置

内容的提问来源于stack exchange,提问作者iamafasha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:10:39