將外掛程式欄位新增至 Block Factory

Blockly 開發人員工具可讓您使用積木建立自訂積木!除了 Blockly 核心隨附的欄位,這個程式庫也支援以外掛程式形式發布的欄位。如果您已建立自訂欄位,可以按照本指南的說明,在 Block Factory 中新增對該欄位的支援。自訂欄位必須先發布至 npm,才能新增支援。此外,您也必須承諾更新欄位,以配合 Blockly 的變更,否則我們日後可能需要從 Block Factory 移除該欄位。

在積木工廠中開發

Block Factory 的原始碼位於 blockly-samples 存放區的 examples/developer-tools 目錄中。

如要提交對 blockly-samples 中開發人員工具的變更,請按照 blockly-samples 的一般開發步驟操作。不過,與外掛程式不同的是,您需要直接從 examples/developer-tools 目錄執行 npm install,而不是在 blockly-samples 的根層級執行。

安裝外掛程式

如要讓 Block Factory 在預覽畫面中顯示自訂欄位,必須先安裝自訂欄位。將欄位新增為開發人員工具的 npm 依附元件。然後在 developer-tools/src/blocks/index.ts 中註冊或完成任何其他必要設定。

為欄位建立區塊

由於 Block Factory 會使用積木建立自訂積木,因此您需要代表自訂欄位的積木。

建立區塊定義

您需要為欄位設計區塊;如要取得中繼資料,甚至可以使用 Block Factory 設計區塊!這個區塊應允許使用者設定欄位所需的設定,例如預設值和名稱。將這個區塊定義新增至 developer-tools/src/blocks/fields.ts,並在 developer-tools/src/blocks/index.ts 中匯入。

將積木新增至工具箱

接著,您需要將這個方塊新增至工具箱定義,讓使用者可以存取。工具箱定義位於 developer-tools/src/toolbox.ts。您的區塊應新增至「Fields」(欄位) 類別。

程式碼生成器

Block Factory 會使用您在 Blockly 中熟悉的程式碼產生器系統。每個區塊都有一個區塊程式碼產生器,適用於 Block Factory 產生的每種輸出類型,而父項區塊會將子項區塊的程式碼組合成正確的輸出內容。如要新增自訂欄位的支援功能,您必須為每個 Code Generator 類別新增區塊程式碼產生器函式。

output-generators/fields 目錄中,為欄位區塊建立檔案。您將為下列每個產生器,將區塊程式碼產生器新增至這個檔案。在 blocks/index.ts 檔案中匯入這個檔案,將方塊程式碼產生器函式載入應用程式。

JavaScript 定義

javascriptDefinitionGenerator 會建立程式碼,並納入包含自訂欄位的區塊 JavaScript 定義中。通常這表示區塊程式碼產生器應傳回類似 .appendField(new YourFieldConstructor(arg1, arg2), 'userSpecifiedName') 的程式碼行。請注意,這行程式碼包含半形分號,因為含有多個欄位的輸入內容會將多個呼叫項目鏈結在一起。appendField建構函式中的引數會從使用者在欄位區塊中設定的值擷取。以下是 FieldAngle 的方塊程式碼產生器範例:

javascriptDefinitionGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: JavascriptDefinitionGenerator,
): string {
  const name = generator.quote_(block.getFieldValue('FIELDNAME'));
  const angle = block.getFieldValue('ANGLE');
  return `.appendField(new FieldAngle(${angle}), ${name})`;
};

使用者從 Block Factory 工具箱的「Fields」類別拖曳的角度方塊有兩個欄位:

  • FIELDNAME:使用者可以在自訂區塊中設定欄位名稱
  • ANGLE:使用者可以設定預設角度值

在這個程式碼方塊產生器中,我們會取得預設角度值,並將其做為唯一引數傳遞至 FieldAngle 建構函式。欄位名稱一律會做為 appendField 的第二個引數傳遞。

JSON 定義

jsonDefinitionGenerator 類似,但會輸出與欄位對應的 JSON 區塊定義部分。通常這個程式碼是 JSON 物件,包含:

  • type:對應於 Blockly 欄位登錄中的欄位名稱
  • name:使用者可以在自訂區塊中設定欄位名稱
  • 欄位 JSON 初始化方法所需的任何其他自訂屬性。

以下是 FieldAngle 的範例:

jsonDefinitionGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: JsonDefinitionGenerator,
): string {
  const code = {
    type: 'field_angle',
    name: block.getFieldValue('FIELDNAME'),
    angle: block.getFieldValue('ANGLE'),
  };
  return JSON.stringify(code);
};

程式碼標頭

程式碼標頭產生器會建立程式碼標頭輸出內容,顯示在 Block Factory 中。使用者可視要載入程式碼的方式,在 esmodule 匯入和指令碼標記之間切換這個輸出內容,因此實際上會有兩個不同的產生器執行個體,分別對應一種情況。您必須為每個項目新增程式碼產生器。以下是 FieldAngle 的範例:

importHeaderGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: CodeHeaderGenerator,
): string {
  generator.addHeaderLine(
    `import {registerFieldAngle, FieldAngle} from '@blockly/field-angle';`,
  );
  generator.addHeaderLine(`registerFieldAngle();`);
  return '';
};

scriptHeaderGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: CodeHeaderGenerator,
): string {
  generator.addHeaderLine(
    `<script src="https://unpkg.com/@blockly/field-angle"></script>`,
  );
  generator.addHeaderLine(`registerFieldAngle();`);
  return '';
};

這些產生器都有名為 addHeaderLine 的方法,可讓您指定應在程式碼中使用欄位前呼叫的程式碼行。通常包括匯入欄位或透過指令碼標記載入欄位,以及呼叫函式,向 Blockly 的欄位登錄檔註冊欄位。

對於這兩個程式碼產生器,所有程式碼都應透過呼叫 addHeaderLine 新增。即使自訂欄位區塊在一個自訂區塊中多次使用,這項函式也能確保每個標題行只顯示一次。區塊程式碼產生器應傳回空白字串。

產生器存根

最後是產生器,可為欄位建立產生器存根。在這個程式碼方塊產生器中,您將編寫程式碼,產生可協助使用者編寫程式碼的程式碼,而這些程式碼又會產生程式碼。是不是有點複雜?其實比想像中簡單得多!

自訂區塊的產生器存根包含預先建立的變數,代表區塊上的每個欄位。然後,使用者必須TODO完成組裝所有這些變數,成為自訂積木會傳回的最終程式碼字串。也就是說,通常所有方塊程式碼產生器只需要傳回建立這個自訂變數的程式碼行即可。假設使用者要建立自訂積木,在畫布上加入陽光。他們在區塊中新增角度欄位,並命名為「"SUN_DIRECTION"」。這個區塊的產生器存根會包含 const angle_sun_direction = block.getFieldValue("SUN_DIRECTION"); 這一行。這是角度欄位的方塊程式碼產生器需要傳回的程式碼行:

generatorStubGenerator.forBlock['field_angle'] = function (
  block: Blockly.Block,
  generator: GeneratorStubGenerator,
): string {
  const name = block.getFieldValue('FIELDNAME');
  const fieldVar = generator.createVariableName('angle', name);
  return `const ${fieldVar} = block.getFieldValue(${generator.quote_(
    name,
  )});\n`;
};

如要取得變數的標準化名稱,可以呼叫 generator.createVariableName,並傳入欄位類型 (例如 anglenumber 等),以及使用者為欄位命名的名稱。

測試

撰寫完所有這些片段後,您應該就能在 blockly-samples/examples/developer-tools 目錄中執行 npm start,啟動 Block Factory。您應該可以從欄位類別拖曳方塊、將方塊新增至方塊的輸入內容,並觀察輸出內容的變化。確認區塊的預覽畫面正確無誤,且每個輸出區段的程式碼都正確。