Monaco Editor断点基础功能详解

目录

前言

实现一:鼠标点击创建断点

实现二:自定义断点样式

实现三:添加断点创建/取消逻辑


前言

最近公司要求用Monaco Editor实现类似vscode断点功能,具体成果如下

我的需求:

  1. 鼠标点击行号增加/取消断点
  2. 支持自定义断点样式

实现一鼠标点击创建断点

首先在创建editor实例时设置glyphMargin:true,这是为了启用图形边距的渲染,在vscode种是默认为true,但在monaco editor中默认为false。

 editor = monaco.editor.create(dom, {
        ...,    // 你的其他配置
        glyphMargin: true,
})

接下来需要监听鼠标事件onMouseDown,这里我是用的react写法

 const onToggleBreakPoint = useCallback(() => {
    editor.onMouseDown((e: { target }) => {
      const { type, position } = e.target;
      if (![2].includes(type)) return;
      ...    // 鼠标点击回调操作
    });
  }, []);

在回调函数中获取到event事件,其中type===2时,表示点击区域为创建断点区域(有时候需要点击面积扩大时可以加上3,4类型)

现在通过回调event事件得到position,创建断点对象

// 创建断点范围
const range = {
          startLineNumber: position.lineNumber,
          startColumn: 1,
          endLineNumber: position.lineNumber,
          endColumn: 1,
};
// 创建断点对象
const breakPointDec = {
          range,
          options: {
            isWholeLine: true,
            className: "contentClass",
            marginClassName: "myGlyphMarginClass",    // 断点css样式类
            stickiness:
              monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
          },
};

// 设置断点
editor.getModel().deltaDecorations([], [breakPointDec]);

这里注意stickiness,亲测必须设置该属性为monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,才能让断点成功跟随行号,stickiness具体属性如下

实现二:自定义断点样式

.myGlyphMarginClass {
  top: 4px !important;
  left: 10px !important;
  width: 10px !important;
  height: 10px !important;
  background: red !important;
  border-radius: 50%;
}

实现三:添加断点创建/取消逻辑

大概思路:

通过editor.getModel().getLineDecorations(position.lineNumber)获取行装饰器,返回的是array,通过遍历行装饰器查找className="myGlyphMarginClass"的装饰id且存储该id,后续判断有用。

判断decorationIds长度,若为0则表示需要创建断点,反之则为取消断点。

const editor = monaco.editor.create(dom, {
        ...,    // 你的其他配置
        glyphMargin: true,
});

const decorationIds = []; 

editor.onMouseDown((e: { target }) => {
      const { type, position } = e.target;
      if (![2, 3, 4].includes(type)) return;

      const lineDecoration = editor.getModel().getLineDecorations(position.lineNumber);
      let flagId = "";
      lineDecoration.forEach((decoration) => {
        if (decoration.options.marginClassName === "myGlyphMarginClass") {
          decorationIds.push(decoration.id);
          flagId = decoration.id;
        }
      });

      if (decorationIds.length === 0) {
        const range = {
          startLineNumber: position.lineNumber,
          startColumn: 1,
          endLineNumber: position.lineNumber,
          endColumn: 1,
        };
        const breakPointDec = {
          range,
          options: {
            isWholeLine: true,
            className: "contentClass",
            marginClassName: "myGlyphMarginClass",
            stickiness:
              monaco.editor.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
          },
        };

        editor.getModel().deltaDecorations([], [breakPointDec]);
      } else {
        const index = decorationIds.findIndex((id) => id === flagId);
        editor.getModel().deltaDecorations(decorationIds, []);
        decorationIds.splice(index, 1);
      }
    });

 以上方案如有错误之处,还请各位指出,后续会进行改正

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值