定义屏蔽设置

区块定义描述了区块的外观和行为,包括文本、 颜色、形状以及它能连接到哪些其他方块

JSON 格式与 JavaScript API

Blockly 采用两种方法定义块:JSON 对象和 JavaScript 函数。 JSON 格式旨在简化本地化工作 制定流程时 。最好使用 JSON 格式 定义方块的方法

但是,JSON 格式无法直接定义高级功能, 作为更改器或验证器。这些内容必须使用 JavaScript 编写,通常如下: 扩展程序

使用 Blockly 的原始 JavaScript 实现的应用也可以编写 将代码块定义直接传递到较低级别的 Blockly API 函数调用,如下所示: 。

JSON

Blockly.defineBlocksWithJsonArray([{
  "type": "string_length",
  "message0": 'length of %1',
  "args0": [
    {
      "type": "input_value",
      "name": "VALUE",
      "check": "String"
    }
  ],
  "output": "Number",
  "colour": 160,
  "tooltip": "Returns number of letters in the provided text.",
  "helpUrl": "http://www.w3schools.com/jsref/jsref_length_string.asp"
}]);

JavaScript

Blockly.Blocks['string_length'] = {
  init: function() {
    this.appendValueInput('VALUE')
        .setCheck('String')
        .appendField('length of');
    this.setOutput(true, 'Number');
    this.setColour(160);
    this.setTooltip('Returns number of letters in the provided text.');
    this.setHelpUrl('http://www.w3schools.com/jsref/jsref_length_string.asp');
  }
};

init 函数可创建块的形状。在目前的语境中, 函数,关键字 this 是所创建的实际块。

两个示例加载相同的“string_length”。

在 Web 上,系统会使用 initJson 函数加载 JSON 格式。 这也允许在 Blockly 网页中混合使用这两种格式。时间是 最好尽可能使用 JSON 定义块,并使用 JavaScript 。

下面是一个主要使用 JSON 定义的块示例, 但通过使用 JavaScript API 进行了扩展,以提供动态提示。

JavaScript

var mathChangeJson = {
  "message0": "change %1 by %2",
  "args0": [
    {"type": "field_variable", "name": "VAR", "variable": "item", "variableTypes": [""]},
    {"type": "input_value", "name": "DELTA", "check": "Number"}
  ],
  "previousStatement": null,
  "nextStatement": null,
  "colour": 230
};

Blockly.Blocks['math_change'] = {
  init: function() {
    this.jsonInit(mathChangeJson);
    // Assign 'this' to a variable for use in the tooltip closure below.
    var thisBlock = this;
    this.setTooltip(function() {
      return 'Add a number to variable "%1".'.replace('%1',
          thisBlock.getFieldValue('VAR'));
    });
  }
};

方块颜色

区块的主要颜色由 JSON colour 属性定义,即 block.setColour(..) 函数, 或者使用“主题”并定义一个区块 样式。

JSON

{
  // ...,
  "colour": 160,
}

JavaScript

init: function() {
  // ...
  this.setColour(160);
}

请参阅图块颜色指南 了解详情。

语句连接

用户可以使用 nextStatementpreviousStatement 个连接器。在 Blockly 的标准布局中,这些连接 在顶部和底部,图块垂直堆叠在一起。

包含上一个连接器的块不能包含 输出连接器,反之亦然。术语 statement block 是指没有值输出的块。语句块通常包含 以及上一条连接的信息。

nextStatementpreviousStatement 连接可以是 typed、 但标准区块中没有使用这一功能。

下一个连接

在块的底部创建一个点,以便可用于其他语句 堆叠在其下方具有下一个连接但没有上一个连接的块 通常代表事件,可配置为 帽子

JSON

非类型化:

{
  ...,
  "nextStatement": null,
}

已输入(极少):

{
  "nextStatement": "Action",
  ...
}

JavaScript

非类型化:

this.setNextStatement(true);  // false implies no next connector, the default

已打字(罕见):

this.setNextStatement(true, 'Action');

上一个连接

在块的顶部创建一个凹口,以便可以作为堆栈连接 语句。

具有先前连接的块不能有输出连接。

JSON

非类型化:

{
  ...,
  "previousStatement": null,
}

已输入(极少):

{
  "previousStatement": "Action",
  ...
}

JavaScript

非类型化:

this.setPreviousStatement(true);  // false implies no previous connector, the default

已打字(罕见):

this.setPreviousStatement(true, 'Action');

块输出

一个块可以有一个输出,在 前沿。输出连接到值输入。包含输出的块 通常称为值块

JSON

非类型化:

{
  // ...,
  "output": null,
}

输入的内容:

{
  // ...,
  "output": "Number",
}

JavaScript

非类型化:

init: function() {
  // ...
  this.setOutput(true);
}

输入的内容:

init: function() {
  // ...
  this.setOutput(true, 'Number');
}

包含输出连接器的块不能同时具有之前的语句标记。

屏蔽输入源

一个块包含一个或多个输入,其中每个输入都有 字段,可能在连接中结束。这里有一些 各种类型的内置输入。

  • 值输入:连接到设备的输出连接 值块math_arithmetic 块(加法、减法)是一个 具有两个值输入的块示例。
  • 语句输入:连接到 语句块旧连接。通过 when 循环的嵌套部分是语句输入的一个示例。
  • 虚拟输入:没有块连接。在以下情况下,会视为换行符: 代码块配置为使用外部值输入。
  • 结束行输入:没有块连接,始终像 换行符。

您还可以创建自定义输入,以支持自定义

JSON 格式和 JavaScript API 使用略微不同的模型来描述 其输入。

JSON 中的输入和字段

JSON 定义的块采用插值序列的形式 消息字符串(message0message1...),其中每个插值标记 (%1%2...)是一个字段或输入端(因此输入连接器 在消息内呈现)。argsN这种格式 旨在促进国际化进程

JSON

{
  "message0": "set %1 to %2",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "item",
      "variableTypes": [""]
    },
    {
      "type": "input_value",
      "name": "VALUE"
    }
  ]
}

插值令牌必须与 args0 数组完全匹配:没有重复项, 不会有任何遗漏。令牌可按任意顺序存在, 更改区块的布局。

插值令牌两侧的文本都会去掉空格。 使用字符 % 的文本(例如,当引用百分比时)应使用 %%,这样就不会将其解释为插值标记。

实参和实参类型的顺序决定了 。更改其中某个字符串可能会完全改变代码块的布局。 对于具有不同字词顺序的语言,这一点尤为重要 比英语更出色。假设有一个假设的语言,其中 "set %1 to %2"(使用为 )需要反转为 "put %2 in %1"。更改 这一字符串(并保留 JSON 的其余部分 将生成以下代码块:

Blockly 自动更改字段顺序,创建虚拟输入, 以及从外部输入到内部输入。

Blockly 还会自动替换消息中的任何换行符 (\n) 带有结束行输入的字符串。

JSON

{
  "message0": "set %1\nto %2",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "item",
      "variableTypes": [""]
    },
    {
      "type": "input_value",
      "name": "VALUE"
    }
  ]
}

参数

每个消息字符串都与包含相同数字的 args 数组配对。对于 例如,message0args0 搭配使用。插值令牌 (%1, %2, ...) 引用 args 数组的项。每个对象都有 type 字符串。其余参数因类型而异:

您也可以定义自己的自定义字段自定义输入并将其作为参数传递。

每个对象可能还有一个 alt 字段。如果 Blockly 没有 识别对象的 type,则系统会使用 alt 对象来代替它。对于 例如,如果向 Blockly 添加了 field_time 新字段,则使用 此字段可以使用 alt 为旧版本定义 field_input 回退 Blockly 的

JSON

{
  "message0": "sound alarm at %1",
  "args0": [
    {
      "type": "field_time",
      "name": "TEMPO",
      "hour": 9,
      "minutes": 0,
      "alt":
        {
          "type": "field_input",
          "name": "TEMPOTEXT",
          "text": "9:00"
        }
    }
  ]
}

alt 对象可能具有自己的 alt 对象,因此允许链接。 最终,如果 Blockly 无法在 args0 数组中创建对象( 尝试任何 alt 对象),系统会跳过该对象。

如果存在 message 字符串以未包含在输入中的文本或字段结尾。 因此,如果块上的最后一个输入是虚拟输入,则可能会从 args 数组,且不需要插值到 message 中。通过 自动添加尾随虚拟输入可让翻译人员 message,而无需修改 JSON 的其余部分。请参阅 "set %1 to %2"(无虚拟输入)和 "put %2 in %1"(已添加虚拟输入) 。

implicitAlign0

在极少数情况下,需要对齐自动创建的尾随虚拟输入 发送到 "RIGHT""CENTRE"。如果未指定,则默认值为 "LEFT"

在下面的示例中,message0"send email to %1 subject %2 secure %3" Blockly 会自动为第三行添加虚拟输入。设置 将 implicitAlign0 设置为 "RIGHT" 会强制该行右对齐。这个 对齐方式适用于 JSON 中未明确定义的所有输入 块定义,包括替换换行符的结束行输入 ('\n')。此外,还有一个已弃用的属性 lastDummyAlign0 其行为与 implicitAlign0 相同。

在设计 RTL(阿拉伯语和希伯来语)块时,左边和右边是相反的。 因此,"RIGHT" 会将字段左对齐。

message1args1implicitAlign1

有些区块会自然地分为两个或更多个独立部分。 假设有以下两行的重复代码块:

如果此块是使用单个消息描述的,则 message0 属性 将为 "repeat %1 times %2 do %3"。这对于翻译人员来说很难理解, 我们很难解释 %2 替换的含义。%2 虚拟形象 输入可能在某些语言中甚至不需要。可能有多个 希望共享第二行文字的文本块。更好的方法 让 JSON 使用多个消息和参数属性:

JSON

{
  "type": "controls_repeat_ext",
  "message0": "repeat %1 times",
  "args0": [
    {"type": "input_value", "name": "TIMES", "check": "Number"}
  ],
  "message1": "do %1",
  "args1": [
    {"type": "input_statement", "name": "DO"}
  ],
  "previousStatement": null,
  "nextStatement": null,
  "colour": 120
}

可以定义任意数量的 messageargsimplicitAlign 属性 是 JSON 格式,从 0 开始,依序递增。请注意, Block Factory 无法将消息拆分为多个部分, 手动执行此操作非常简单。

JavaScript 中的输入和字段

JavaScript API 为每种输入类型都提供了一个 append 方法:

JavaScript

this.appendEndRowInput()
    .appendField('for each')
    .appendField('item')
    .appendField(new Blockly.FieldVariable());
this.appendValueInput('LIST')
    .setCheck('Array')
    .setAlign(Blockly.inputs.Align.RIGHT)
    .appendField('in list');
this.appendStatementInput('DO')
    .appendField('do');
this.appendDummyInput()
    .appendField('end');

每个附加方法都可以接受代码生成器使用的标识符字符串。虚拟 结束行输入很少需要引用,并且标识符通常会 未设置。

JavaScript API 还包含一个通用的 appendInput 方法,用于将 自定义输入。请注意,在这种情况下,标识符应该 直接传递给自定义输入的构造函数。

JavaScript

this.appendInput(new MyCustomInput('INPUT_NAME'))
    .appendField('an example label')

所有 appendInput 方法(包括通用方法和非通用方法)都会返回 输入对象,以便使用方法链接进一步配置它们。那里 是三种用于配置输入的内置方法。

setCheck

JavaScript

input.setCheck('Number');

此可选函数用于对已连接的输入进行类型检查。如果给定 null 的参数(默认值),则此输入可以连接到任何块。 如需了解详情,请参阅类型检查

setAlign

JavaScript

input.setAlign(Blockly.inputs.Align.RIGHT);

此可选函数用于对齐字段(请参阅下文)。有三个 自描述值,这些值可以作为参数传递给此函数: Blockly.inputs.Align.LEFTBlockly.inputs.Align.RIGHTBlockly.inputs.Align.CENTER

在设计 RTL(阿拉伯语和希伯来语)块时,左边和右边是相反的。 因此,Blockly.inputs.Align.RIGHT 会将字段左对齐。

appendField

在创建输入并使用 appendInput 附加到块后, 还可以选择在输入中附加任意数量的字段。这些字段 通常用作标签,以描述每个输入的用途。

JavaScript

input.appendField('hello');

最简单的字段元素是文本。Blockly 的惯例是 小写文本,专有名(例如 Google、SQL)除外。

输入行可以包含任意数量的字段元素。多个appendField 调用可以链接在一起,以便高效地将多个字段添加到同一 输入行。

JavaScript

input.appendField('hello')
     .appendField(new Blockly.FieldLabel('Neil', 'person'));

appendField('hello') 调用实际上是使用显式 FieldLabel 构造函数:appendField(new Blockly.FieldLabel('hello'))。 只有在指定 类名称,以便使用 CSS 规则设置文本的样式。

内嵌与外部

屏蔽输入可呈现为外部或内部。

块定义可以指定一个可选的布尔值,用于控制 是否内嵌。如果为 false,则任何值输入都将是外部输入(例如 (左侧代码块)。如果为 true,则任何值输入都将是内嵌的(例如 右方块)。

JSON

{
  // ...,
  "inputsInline": true
}

JavaScript

init: function() {
  // ...
  this.setInputsInline(true);
}

如果未定义,Blockly 将使用一些启发法来猜测哪种模式 最好。假设 Blockly 做出正确选择,不定义此字段 因为系统可以自动翻译 不同模式。请参阅 "set %1 to %2"(外部输入)的 JSON 示例和 "put %2 in %1"(内嵌输入)。

当代码块可能包含数字等较小的输入时,请使用内嵌输入。 如果 collapse,用户可以通过上下文菜单切换此选项。 配置启用(如果工具箱中有类别,则默认为 true)。

字段

字段定义了块中的大部分界面元素。其中包括 字符串标签、图片和输入, 字面量数据 例如字符串和数字。最简单的示例就是 math_number 代码块, 该函数使用 field_input 来让用户输入数字。

字段会按照 appendField.

Blockly 提供了许多内置字段,包括文本输入、颜色选择器 和图片。您也可以创建自己的字段。

→ 详细了解内置字段

→ 详细了解自定义字段创建

图标

图标用于定义显示“meta”的块上的界面元素有关 。

图标会使用 addIcon 附加到区块。

Blockly 提供了许多内置图标,包括评论图标 和警告图标。您也可以创建自己的图标。

→ 详细了解创建自定义图标

提示

用户将鼠标悬停在方块上时,工具提示可提供即时帮助。 如果文本过长,会自动换行。

JSON

{
  // ...,
  "tooltip": "Tooltip text."
}

JavaScript

init: function() {
  this.setTooltip("Tooltip text.");
}

在 JavaScript API 中,提示也可以定义为函数,而不是 静态字符串。这样可提供动态帮助。查看 math_arithmetic 根据所选择的下拉菜单选项而变化的提示示例 所选对象。

JavaScript

Blockly.Blocks['math_arithmetic'] = {
  init: function() {
    // ...

    // Assign 'this' to a variable for use in the tooltip closure below.
    var thisBlock = this;
    this.setTooltip(function() {
      var mode = thisBlock.getFieldValue('OP');
      var TOOLTIPS = {
        'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,
        'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,
        'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,
        'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,
        'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER
      };
      return TOOLTIPS[mode];
    });
  }
};

使用 JavaScript API,块可以指定函数,而不是静态 字符串,返回提示字符串。这样就可以显示动态提示。 有关示例,请参阅 math_arithmetic

自定义

您还可以通过提供自定义呈现来自定义提示的外观 函数。创建一个接受两个形参的函数:

  • 首先,一个 <div> 元素,您将在其中渲染内容
  • 第二个元素是鼠标悬停时显示的实际元素 提示

在函数正文中,您可以将任何内容渲染到 div。如需获取在鼠标悬停的块上定义的提示字符串,您可以 调用 Blockly.Tooltip.getTooltipOfObject(element);,其中 element 是 上述第二个参数。

最后,注册此函数,以便 Blockly 可以在适当的时间调用它:

Blockly.Tooltip.setCustomTooltip(yourFnHere);

有关示例,请参见 自定义提示演示

“帮助”网址

屏蔽设置可以有关联的帮助页面。这适用于 使用 Blockly for Web,方法是右键点击相应块,然后选择“Help”(帮助) 从上下文菜单中操作如果此值为 null,则菜单将显示为灰色 。

JSON

{
  // ...,
  "helpUrl": "https://en.wikipedia.org/wiki/For_loop"
}

JavaScript

init: function() {
  // ...
  this.setHelpUrl('https://en.wikipedia.org/wiki/For_loop');
}

使用 JavaScript API,块可以指定函数,而不是静态 字符串,后者会返回网址字符串,从而支持动态帮助。

更改监听器和验证器

块可以包含更改监听器函数,在对 工作区(包括与屏蔽设置无关的工作区)。这些参数主要用于 设置屏蔽的警告文字或类似的用户通知, 工作区。

该函数是通过使用函数调用 setOnChange 添加的, 在初始化期间或通过 JSON 扩展程序(如果您计划使用此扩展程序) 在所有平台上都有效

JSON

{
  // ...,
  "extensions":["warning_on_change"],
}

Blockly.Extensions.register('warning_on_change', function() {
  // Example validation upon block change:
  this.setOnChange(function(changeEvent) {
    if (this.getInput('NUM').connection.targetBlock()) {
      this.setWarningText(null);
    } else {
      this.setWarningText('Must have an input block.');
    }
  });
});

JavaScript

Blockly.Blocks['block_type'] = {
  init: function() {
    // Example validation upon block change:
    this.setOnChange(function(changeEvent) {
      if (this.getInput('NUM').connection.targetBlock()) {
        this.setWarningText(null);
      } else {
        this.setWarningText('Must have an input block.');
      }
    });
  }
}

系统会调用函数,传入 更改事件。 在该函数内,this 引用块实例。

由于该函数在出现任何更改时都会调用,因此如果使用,开发者应确保 监听器就会快速运行此外,还应警惕对工作区所做的更改 可能会级联或环回监听器的请求。

请参阅controls_flow_statementslogic_compareprocedures_ifreturn 作为示例。

请注意,可修改字段有自己的事件监听器,用于验证输入 并产生副作用

更改者

赋值函数允许高级方块改变形状,最显著的原因是 用户打开一个对话框以添加、删除或重新排列组件。变更可以是 使用 mutator 键通过 JSON 添加。

JSON

{
  // ...,
  "mutator":"if_else_mutator"
}

每个块的配置

块实例具有一些属性,可用于配置其行为方式 用户。这些属性可用于限制工作区,使其反映 域属性(例如,恰好只有一个“start”事件)、 用户的工作量(例如教程)。

可删除状态

block.setDeletable(false);

如果此政策设为 false,用户将无法删除该屏蔽设置。屏蔽默认值 在可修改的工作区上可删除。

任何块(即使是无法删除的块)都可以以编程方式删除:

block.dispose();

可编辑状态

block.setEditable(false);

如果此政策设为 false,用户将无法更改该块的字段 (例如下拉菜单和文本输入)。“块”默认设置为可修改的可修改状态 工作区。

可移动状态

block.setMovable(false);

如果此政策设为 false,用户将无法直接移动相应图块。一个 作为另一个块的子块的不移动块可能无法与 但如果父级移动,该块也会随父级块一起移动。方块 默认设置为可在可修改的工作区中移动。

任何块(即使是不可移动块)置于 工作区。

block.moveBy(dx, dy)

块在工作区上的起始位置默认为 (0, 0)。

禁止使用数据流量

this.data = '16dcb3a4-bd39-11e4-8dfc-aa07a5b093db';

data 是附加到块的可选、任意字符串。当 则数据字符串也随之序列化。这包括以下情况: 文本块被复制或复制/粘贴。

这通常用于将块与外部资源相关联。

在序列化为 JSON 后,数据会作为顶级属性存储在 块中:

{
  "type": "my_block",
  "data": "16dcb3a4-bd39-11e4-8dfc-aa07a5b093db",
  // etc..
}

在序列化为 XML(旧的冰盒序列化系统)时,数据字符串 存储在以下块内的 <data></data> 标记中:

<block type="my_block">
  <data>16dcb3a4-bd39-11e4-8dfc-aa07a5b093db</data>
  <!-- etc... -->
</block>

破坏

块有一个 destroy 钩子,在从 工作区。这可用于销毁任何后备数据模型/外部 与块关联的不再需要的资源。

JSON

{
  // ...,
  "extensions":["destroy"],
}

Blockly.Extensions.registerMixin('destroy', {
  destroy: function() {
    this.myResource.dispose();
  }
});

JavaScript

Blockly.Blocks['block_type'] = {
  destroy: function() {
    this.myResource.dispose();
  }
}

destroy 方法会在处理该块的父级之后调用,但

上下文菜单

默认情况下,区块具有一个右键点击上下文菜单,以方便用户执行相关操作 例如添加注释或复制代码块。

您可以通过执行以下操作来停用单个块的上下文菜单:

block.contextMenu = false;

您还可以自定义菜单中显示的选项。自定义菜单: 请参阅 上下文菜单文档。 要为单个块自定义菜单,您可以使用 customContextMenu。此函数接受一个菜单选项数组, 并在适当位置进行修改,这意味着您可以添加和移除项。

每个菜单选项都是一个具有以下三个属性的对象:

  • text 是显示文本。
  • enabled 是一个布尔值。停用后,该选项仍会显示,但显示为灰色 文本。
  • callback 是点击该选项时要调用的函数。