blockly -- 定义块

定义块

块定义描述了块的外观和行为,包括文本,颜色,形状以及它可以连接的其他块。

定义自定义块后,每个平台都会以不同的方式加载这些定义,详细信息请参见 网络和 Android特定配置指南。

 

JSON格式与JavaScript API

Blockly有两种定义块的方式:JSON对象和JavaScript函数。JSON格式是跨平台的,因此可以使用相同的代码在Web,Android和iOS上定义块。此外,JSON格式旨在在开发具有不同单词顺序的语言时简化本地化过程。JSON格式是定义块的首选方法。

但是,JSON格式无法直接定义高级功能,例如变异器或验证器。这些必须以平台的本机代码,JavaScript,Java或Swift编写,通常作为 扩展

使用Blockly的原始JavaScript实现的应用程序也可以直接将块定义写入较低级别的Blockly API函数调用,如下面的各种JavaScript示例所示。

//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');
  }
};

//json
{
  "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"
}

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

在Web上,使用initJson函数加载JSON格式。这也允许将两种格式混合在Blockly网页中。最好在可能的情况下使用JSON定义您的块,并且仅将JavaScript用于JSON不支持的部分块定义。

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

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'));
    });
  }
};

Block colour

块的主颜色由JSON colour属性block.setColour(..)函数定义,或者通过使用主题和定义块样式来定义。

//JSON

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

//javascript

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

有关详细信息,请参阅块颜色指南。

Statement Connections (块连接)

用户可以使用nextStatement和previousStatement连接器创建块序列。在Blockly的标准布局中,这些连接位于顶部和底部,块垂直堆叠。

带有前一个连接器的块不能有输出连接器,反之亦然。语句块是指没有值输出的块。语句块通常同时具有前一个连接和下一个连接。

可以键入nextStatement和previousStatement连接,但标准块不使用此功能。

Next Connection (向下连接)

在块的底部创建一个点,以便其他语句可以堆叠在它的下面。具有下一个连接但没有上一个连接的块通常表示一个事件,并且可以配置为使用hat呈现。

// JSON

Untyped:

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

Typed (rare):

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

//javascript

Untyped:

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

Typed (rare):

this.setNextStatement(true, 'Action');

Previous Connection  (向上连接)

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

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

//JSON

Untyped:

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

Typed (rare):

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



//javascript

Untyped:

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

Typed (rare):

this.setPreviousStatement(true, 'Action');

Block Output (块输出)

块可以具有单个输出,表示为前缘上的公拼图连接器。输出连接到值输入。具有输出的块通常称为值块。

//JSON


Untyped:

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

Typed:

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


//javascript

Untyped:

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

Typed:

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

带有输出连接器的块也不能有前一个语句槽。

Block Inputs

一个块有一个或多个输入,其中每个输入是可能以连接结束的标签和字段序列。有三种输入类型,与连接类型匹配:

Value input:连接到值块的输出连接。math_算术块(加法、减法)是具有两个值输入的块的示例。

Statement input:连接到语句块的前一个连接。while循环的嵌套部分是语句输入的一个示例。

Dummy input:没有块连接。当块被配置为使用外部值输入时,其行为类似于换行符。

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

Inputs and Fields in JSON

JSON定义的块被构造为一个插值消息字符串序列(message0、message1,…),其中每个插值标记(%1、%2,…)是匹配的JSON argsN数组中的字段或输入端(因此,在消息中输入连接器呈现)。这种格式旨在使国际化变得容易。

{
  "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的其余部分不变)将导致以下块:

块自动改变字段的顺序,创建一个虚拟输入,并从外部输入切换到内部输入。

Args

每个消息字符串都与一个相同编号的args数组配对。例如,message0 与args0一起使用。插值标记(%1、%2,…)引用args数组的项。每个对象都有一个类型字符串。其余参数因类型而异:

每个对象也可能有alt字段。如果Blockly无法识别对象的类型,则使用alt对象代替它。例如,如果将名为field_time的新字段添加到Blockly,则使用此字段的块可以使用alt为Blockly的旧版本定义field_input fallback:

{
  "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对象之后),则只跳过该对象。

如果消息字符串以不包含在输入中的文本或字段结尾,则将自动在块的末尾添加一个伪输入。因此,如果块上的最后一个输入是伪输入,则可以从args数组中省略它,并且不需要在消息中插入。自动添加拖尾伪输入允许转换器更改消息,而无需修改JSON的其余部分。请参阅本页前面的“将%1设置为%2”(无伪输入)和“将%2放入%1”(添加了伪输入)示例。

lastDummyAlign0

在极少数情况下,自动创建的尾部伪输入需要与“右”或“中心”对齐。如果未指定,则默认值为“左”。

在下面的示例中,message0 is "send email to %1 subject %2 secure %3" ,并为第三行自动添加一个虚拟输入。将lastDummyAlign0设置为“RIGHT”将强制此行右对齐。

在为RTL(阿拉伯语和希伯来语)设计块时,左右颠倒。因此,“RIGHT”将字段与左边对齐。

message1args1lastDummyAlign1

有些区块自然分成两个或多个独立的部分。考虑这个重复块,它有两行:

如果用单个消息描述此块,则message0属性将为“repeat %1次%2执行%3”。这个字符串对于翻译来说很难理解,很难解释%2替换意味着什么。在某些语言中甚至可能不需要%2伪输入。可能有多个块希望共享第二行的文本。一种更好的方法是JSON使用多个消息和args属性:

{
  "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
}

任何数量的消息、参数和lastDummyAlign属性都可以用JSON格式定义,从0开始并按顺序递增。请注意,块工厂不能将消息拆分为多个部分,但手动执行此操作非常简单。

Inputs and Fields in JavaScript

JavaScript API为每个输入类型都包含一个append方法:

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

每个方法都可以采用由代码生成器使用的标识符字符串。虚拟输入很少需要引用,标识符通常不设置。

如上所示,每个方法都通过方法链返回要配置的输入对象。有三个功能用于配置输入。

setCheck

input.setCheck('Number');

此可选功能用于连接输入的类型检查。如果给定的参数为null(默认值),则此输入可以连接到任何块。有关详细信息,请参见类型检查。

setAlign

input.setAlign(Blockly.ALIGN_RIGHT);

此可选功能用于对齐字段(请参见下文)。有三个自描述性值可以作为参数传递给此函数:Blockly.ALIGN_LEFT、Blockly.ALIGN_RIGHT和Blockly.ALIGN_CENTRE。注意“center”的英国拼写。默认为左对齐。

在为RTL(阿拉伯语和希伯来语)设计块时,左右颠倒。因此Blockly.ALIGN_RIGHT会将字段左对齐。

appendField

一旦创建了输入并将其附加到带有append input的块中,就可以选择将任意数量的字段附加到输入中。这些字段通常用作描述每个输入的用途的标签。

input.appendField('hello');

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

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

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

appendField('hello')调用实际上是使用显式FieldLabel构造函数的快捷方式:appendField(new Blockly.FieldLabel('hello'))。只有在指定类名时才希望使用构造函数,以便可以使用CSS规则对文本进行样式设置。

Inline vs. External

块输入可以呈现为外部或内部。

块定义可以指定可选的布尔值,以控制输入是否内联。如果为false,则任何值输入都将是外部的(例如左块)。如果为true,则任何值输入都将内联(如上面的右块)。

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

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

如果没有定义,那么Blockly将使用一些启发式方法来猜测哪种模式是最好的。假设Blockly做出了正确的选择,最好不定义这个字段,因为不同的语言翻译可以自动具有不同的模式。请参阅本页前面的JSON示例“将%1设置为%2”(外部输入)和“将%2放入%1”(内联输入)。

当块可能有小的输入(如数字)时,使用内联输入。如果启用折叠配置(如果工具箱具有类别,则默认为true),则用户可以通过上下文菜单切换此选项。

Fields

字段定义块中的UI元素。其中包括字符串标签、图像和文本数据(如字符串和数字)的输入。最简单的例子是math_number块,可以是field_input(web)或field_number(Android)来输入数字。

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

有关 built-in fields.的更多信息。

有关creating custom fields.的详细信息。

Tooltips

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

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


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

在JavaScript API中,工具提示也可以定义为函数而不是静态字符串。这允许动态帮助。有关工具提示的示例,请参见math_算术,该工具提示会根据选择的下拉选项而更改。

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,块可以指定一个函数,而不是返回工具提示字符串的静态字符串。这允许动态工具提示。例如,参见数学。

Help URL

块可以具有与其关联的帮助页。Blockly for Web的用户可以通过右键单击该块并从上下文菜单中选择“帮助”来使用它。如果此值为空,则菜单将灰显。

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

//javascript

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

使用JavaScript API,块可以指定一个函数,而不是返回URL字符串的静态字符串,从而允许动态帮助。

Change Listeners and Validators

块可以具有对工作区的任何更改(包括与块无关的更改)调用的更改侦听器函数。它们主要用于设置块的警告文本或工作区外的类似用户通知。

通过使用函数调用setOnChange来添加该函数,如果计划在所有平台上使用它,则可以在init期间或通过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.');
      }
    });
  }
}

系统调用函数,传递change事件。在函数内部,这指的是块实例。

因为函数是在任何更改时调用的,如果使用,开发人员应该确保监听器快速运行。还应该注意对工作区的更改,这些更改可能会层叠或循环回侦听器。

有关示例,请参阅controls_flow_statements、logic_compare和procedures_ifreturn块。

请注意,可编辑字段有自己的事件侦听器,用于输入验证并产生副作用。

Mutator

变异器允许高级块更改形状,特别是当用户打开一个对话框来添加、删除或重新排列组件时。可以使用mutator键通过JSON添加mutator。

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

Per-block configuration

块实例具有许多属性,可配置它们对用户的行为方式。它们可以用来约束工作区以反映域的某些属性(例如,只有一个“开始”事件),或者集中用户的精力(例如,教程)。

Deletable State

默认情况下,用户可以删除可编辑工作区(而不是只读)上的任何块。有时,使某些块成为永久性固定装置是有用的。例如,教程框架代码。

block.setDeletable(false);

任何块,包括那些标记为不可删除的块,都可以通过编程方式删除:

block.dispose();

Editable State

block.setEditable(false); 

当设置为false时,用户将无法更改块的字段(例如下拉列表和文本输入)。块在可编辑工作空间上默认为可编辑。

Movable State

block.setMovable(false); 

当设置为false时,用户将无法直接移动块。作为另一个块的子块的不可移动块不能从该块断开,尽管如果父块被移动,它将与其父块一起移动。

块默认为在可编辑工作空间上可移动。

任何块(甚至是不可移动的块)一旦在工作区上,就可以通过编程方式移动。在JavaScript中,调用block.moveBy(dx,dy)。除非另有指定,否则工作区上块的起始位置默认为(0,0)。

Block data (web only)

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

数据是附加到块的可选任意字符串。当保存为XML时,数据字符串存储在一个<data></data>标记中,以便它可以往返返回到一个块。使用数据字符串将块与外部资源关联或用于任何其他自定义目的。

请注意,如果块被复制或复制/粘贴,则数据字符串也会被复制。无法复制或复制/粘贴不可删除的块。

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值