键盘快捷键

Blockly 会维护一个键盘快捷键注册表,用于将按键(或按键组合,如 ctrl-C)映射到操作。注册表已预先填充了许多快捷方式,例如用于复制的 ctrl-Cmeta-C。您可以向注册表中添加快捷方式,也可以从中删除快捷方式。

键盘快捷键的运作方式

快捷方式注册表包含用于对键盘快捷键建模的对象。当用户按下某个键(或组合键)时,Blockly 会执行以下操作:

  1. 检查注册表,看看是否有任何快捷方式适用于该键。如果多个快捷方式使用该键,系统会按注册顺序的反向顺序尝试这些快捷方式。也就是说,系统会先尝试最近注册的快捷方式。

  2. 调用快捷指令的 preconditionFn 函数,该函数用于确定快捷指令是否适用于当前情况。例如,复制快捷键适用于块,但不适用于工作区。如果该快捷方式不适用,Blockly 会尝试列表中的下一个快捷方式(如果有)。

  3. 调用快捷方式的 callback 函数,该函数会执行快捷方式的操作。例如,复制快捷键可复制当前聚焦的对象(例如代码块)。如果此函数返回 true,处理会停止。如果返回 false,Blockly 会尝试列表中的下一个快捷方式(如果有)。

范围

Scope 对象用于标识当前获得焦点的 Blockly 组件。范围对象会传递给 preconditionFncallback,这两个函数会使用范围对象来决定快捷方式是否适用于特定组件,如果适用,则决定如何应用该快捷方式。

如需使用 Scope 对象,请使用其 focusedNode 属性。这是一个实现 IFocusableNode 的对象。用户可以聚焦的所有 Blockly 组件(包括工作区、代码块、字段、注释和您自己的自定义组件)都会实现此接口;如需了解详情,请参阅聚焦系统

例如,preconditionFn 可能会使用 focusedNode 来确保快捷方式仅适用于块。

preconditionFn(workspace, scope) {
  return (scope.focusedNode instanceof Blockly.BlockSvg);
}

KeyboardShortcut 接口

快捷方式注册表中的对象实现了 KeyboardShortcut 接口。此对象包含以下属性。

名称(必填)

快捷方式的唯一名称。此属性不会向用户显示,无需采用人类可读懂的格式。不应翻译。

const logFieldsShortcut = {
  name: 'logFields',
  // ...
};

preconditionFn(可选)

Blockly 会调用此函数来确定快捷方式是否适用于当前情况。如果返回 true,Blockly 会调用 callback。如果返回 false,Blockly 会忽略此快捷方式。例如:

const logFieldsShortcut = {
  // ...
  preconditionFn(workspace, scope) {
    // This shortcut only applies to blocks.
    return (scope.focusedNode instanceof Blockly.BlockSvg);
  },
  // ...
};

如果快捷方式始终适用(不常见),则可以省略此函数。 快捷方式不应省略此函数,然后在 callback 中有条件地执行操作。这样做可防止 Blockly 执行构建显示适用快捷方式的上下文帮助菜单等操作。

回调(可选)

此函数会执行与快捷方式关联的操作。仅当 preconditionFn 返回 true 或不存在时,才会调用此方法。其参数为:

  • workspace:当前的 WorkspaceSvg
  • e:启动快捷方式的 Event
  • shortcutKeyboardShortcut 本身。
  • scope:快捷方式适用的 Scope

如果成功,则返回 true;如果失败,则返回 false

例如:

const logFieldsShortcut = {
  // ...
  callback(workspace, event, shortcut, scope) {
    // preconditionFn required focusedNode to be a BlockSvg.
    for (input of scope.focusedNode.inputList) {
      // Log the values of all named fields. (Label fields usually don't have names.)
      for (field of input.fieldRow) {
        if (field.name) {
          console.log(field.name + ': ' + field.getText());
        }
      }
    }
    return true;
  },
  // ...
};

虽然 callback 是可选的,但通常没有理由不实现它。

keyCodes(可选)

用于激活此快捷方式的键(或键组合)数组。如需识别按键,请使用 Blockly.utils.KeyCodes 中的键码。例如:

const logFieldsShortcut = {
  // ...
  keyCodes: [Blockly.utils.KeyCodes.L],
  // ...
};

如果您想将其他按键映射到现有快捷键(例如,您想向默认快捷键添加按键),可以调用 Blockly.ShortcutRegistry.registry.addKeyMapping。这种情况并不常见。

组合键

如果键盘快捷键是通过组合键(例如同时按住 ControlC)激活的,请通过调用 Blockly.ShortcutRegistry.registry.createSerializedKey 创建序列化的键码:

const ctrlC = Blockly.ShortcutRegistry.registry.createSerializedKey(
  Blockly.utils.KeyCodes.C,       // Keycode of main key
  [Blockly.utils.KeyCodes.CTRL],  // Array of modifier keys
);

const copyShortcut = {
  // ...
  keyCodes: [ctrlC], // Use the serialized keycode
  // ...
};

Control 和 Meta

在 Windows 上,许多快捷键都是通过 Control 键激活的。在 Mac 上,这些键盘快捷键使用的是 Command 键,该键被识别为 META 键码。为了同时支持这两个操作系统,请同时注册 CTRL 按键代码和 META 按键代码。

const ctrlC = Blockly.ShortcutRegistry.registry.createSerializedKey(
  Blockly.utils.KeyCodes.C,
  [Blockly.utils.KeyCodes.CTRL],
);
const metaC = Blockly.ShortcutRegistry.registry.createSerializedKey(
  Blockly.utils.KeyCodes.C,
  [Blockly.utils.KeyCodes.META],
);

const copyShortcut = {
  // ...
  keyCodes: [ctrlC, metaC],
  // ...
};

植入注意事项

Blockly 的键盘事件处理脚本使用 KeyboardEventkeycode 属性,即使该属性已被弃用。

allowCollision(可选)

默认情况下,您只能为给定的按键或按键组合注册一个快捷键。将此属性设置为 true 可让您注册按键(或按键组合),即使已注册了具有相同按键(或按键组合)的快捷键也是如此。

请注意,此属性仅在尝试注册此快捷方式时适用。 它不会阻止其他快捷方式使用相同的键(或组合键)。能否注册取决于其 allowCollision 属性的值。

无论为给定的按键或按键组合注册了多少个快捷方式,最多只会成功执行一个。系统会按注册的相反顺序(从最后注册的快捷方式到最先注册的快捷方式)尝试快捷方式。其中一个快捷方式从其回调返回 true 后,系统不会再尝试其他快捷方式。

元数据(可选)

这是一个包含其他信息的任意对象。它通过 shortcut 参数提供给 callback

添加、删除和修改快捷方式

如需添加新的键盘快捷键,请调用 Blockly.ShortcutRegistry.registry.register

Blockly.ShortcutRegistry.registry.register(logFieldsShortcut);

此函数具有第二个形参 (allowOverrides),可用于替换与您的快捷方式同名的现有快捷方式。请注意,这与 KeyboardShortcut.allowCollision 不同,后者可让您添加名称不同的快捷方式,但使用与现有快捷方式相同的键或键组合。

如需删除键盘快捷键,请调用 Blockly.ShortcutRegistry.registry.unregister 并传递快捷键的名称:

Blockly.ShortcutRegistry.registry.unregister('logFields');

您无法就地修改键盘快捷键。而是需要删除现有快捷方式,然后添加新的快捷方式。例如:

// Get the existing shortcut. getRegistry returns an object keyed by shortcut name.
const allShortcuts = Blockly.ShortcutRegistry.registry.getRegistry();
const modLogFieldsShortcut = allShortcuts[logFieldsShortcut.name];
// Apply the shortcut only to math blocks,
modLogFieldsShortcut.preconditionFn = function (workspace, scope) {
  return (scope.focusedNode instanceof Blockly.BlockSvg &&
          scope.focusedNode.type.startsWith('math_'));
}
// Delete the existing shortcut and add the modified shortcut.
Blockly.ShortcutRegistry.registry.unregister(logFieldsShortcut.name);
Blockly.ShortcutRegistry.registry.register(modLogFieldsShortcut);

默认快捷键

快捷方式注册表中预先填充了许多快捷方式。您可以在 https://github.com/google/blockly/blob/master/core/shortcut_items.ts 中找到这些内容。 快捷方式在 registerXxxx 函数中定义。

键盘导航快捷键

键盘导航插件包含一些快捷键,可让用户通过键盘(例如使用箭头键)在 Blockly 中导航。对于无法使用鼠标的用户(例如行动不便或视障用户),键盘导航至关重要。对于可能希望使用键盘快捷键来提高效率的高级用户,此功能也很有用。