# 覆盖注释图标

你可以覆盖内置注释图标。例如,你可能希望注释的弹出气泡 (opens new window)使用不同的展示方式。

高亮显示注释图标的块

要覆盖注释图标,需要继承 CommentIcon,重写 ICommentIcon 中的部分方法,并注册你的新图标。

提示

Blockly 内置有三类图标:注释、警告、变形器。只有注释图标支持覆盖。

# 继承 CommentIcon

先从继承 CommentIcon 开始:

class MyCommentIcon extends Blockly.icons.CommentIcon {
  constructor(sourceBlock) {
    super(sourceBlock);
  }
}

# 重写 ICommentIcon 与 Icon 中的方法

为了定制图标,可以重写 ICommentIcon 中的方法(下文会分别说明),也可以重写 Blockly.icons.Icon 中的方法(见创建自定义图标)。

不要重写 getType,它必须返回 Blockly.icons.IconType.COMMENT

# 文本

ICommentIcon 要求注释图标必须有文本。getText 需要返回注释文本,setText 需要设置文本并更新相关视觉表现。

getText() {
  return this.text;
}

setText(text) {
  this.text = text;
  this.myRenderMethod();
}

# 气泡

你的自定义注释图标必须实现 IHasBubble 接口以支持序列化。即使你的图标技术上没有气泡,也建议在类上保存可见性状态,这样加载存档时不会丢失“注释是否打开”的信息。

bubbleIsVisible() {
  return this.bubbleVisible;
}

setBubbleVisible(visible: boolean) {
  this.bubbleVisible = visible;
}

关于气泡,见 Use pop-up bubbles (opens new window)

ICommentIcon 还要求实现 getBubbleSizesetBubbleSize。同样,即使没有真实气泡,也建议保存该状态以保持序列化一致性。

getBubbleSize() {
  return this.bubbleSize;
}

setBubbleSize(size) {
  this.bubbleSize = size;
  this.myRenderMethod();
}

ICommentIcon 还要求实现 getBubbleLocationsetBubbleLocation,用于读写气泡在工作区中的位置。

setBubbleLocation(location) {
  this.bubbleLocation = location;
}

getBubbleLocation() {
  return this.bubbleLocation;
}

# 保存和加载

你的自定义注释图标必须实现 ISerializable 接口。状态结构应符合 CommentState

saveState() {
  return {
    text: this.text,
    pinned: this.bubbleVisible,
    height: this.bubbleSize.height,
    width: this.bubbleSize.width,
    x: this.bubbleLocation.x,
    y: this.bubbleLocation.y,
  }
}

loadState(state) {
  this.setText(state.text);
  this.setBubbleVisible(state.pinned);
  this.setBubbleSize(new Blockly.utils.Size(state.width, state.height));
  this.setBubbleLocation(new Blockly.utils.Coordinate(state.x, state.y));
}

关于图标序列化,见 Save and load icons (opens new window)

# 注册你的图标

最后,先注销原有注释图标,再注册你的注释图标,让 Blockly 能实例化你的实现。注销使用字符串 'comment',注册使用 IconTypes.COMMENT

Blockly.icons.registry.unregister('comment');
Blockly.icons.registry.register(Blockly.icons.IconType.COMMENT, myCommentIcon);

注册后,Blockly 会用你的图标替代内置注释图标。比如用户在右键菜单点击 “Add Comment” 时,或调用 myBlock.setCommentText() 时,都会使用新图标实现。