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>標記中,以便它可以往返返回到一個塊。使用數據字符串將塊與外部資源關聯或用於任何其他自定義目的。

請注意,如果塊被複制或複製/粘貼,則數據字符串也會被複制。無法複製或複製/粘貼不可刪除的塊。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章