区块定义描述了区块的外观和行为,包括文本、 颜色、形状以及它能连接到哪些其他方块
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);
}
请参阅图块颜色指南 了解详情。
语句连接
用户可以使用 nextStatement
和
previousStatement
个连接器。在 Blockly 的标准布局中,这些连接
在顶部和底部,图块垂直堆叠在一起。
包含上一个连接器的块不能包含 输出连接器,反之亦然。术语 statement block 是指没有值输出的块。语句块通常包含 以及上一条连接的信息。
nextStatement
和 previousStatement
连接可以是
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 定义的块采用插值序列的形式
消息字符串(message0
、message1
...),其中每个插值标记
(%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
数组配对。对于
例如,message0
与 args0
搭配使用。插值令牌
(%1
, %2
, ...) 引用 args
数组的项。每个对象都有
type
字符串。其余参数因类型而异:
- 字段: <ph type="x-smartling-placeholder">
- 输入内容:
<ph type="x-smartling-placeholder">
- </ph>
input_value
input_statement
input_dummy
input_end_row
您也可以定义自己的自定义字段和 自定义输入并将其作为参数传递。
每个对象可能还有一个 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"
会将字段左对齐。
message1
、args1
、implicitAlign1
有些区块会自然地分为两个或更多个独立部分。 假设有以下两行的重复代码块:
如果此块是使用单个消息描述的,则 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
}
可以定义任意数量的 message
、args
和 implicitAlign
属性
是 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.LEFT
、Blockly.inputs.Align.RIGHT
和
Blockly.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_statements
、logic_compare
和procedures_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
是点击该选项时要调用的函数。