自訂積木、嵌入編輯器、Blockly Games 原理
對開發者而言,Blockly 是一個 JavaScript 程式庫,你把它嵌進自己的網頁,就能得到一個積木編輯器。
這個單元教「動手做一個自訂積木」;若要深入生成器、優先序與自訂語言,請接著看 單元 21–24。
| 元件 | 功能 |
|---|---|
| Toolbox(工具箱) | 定義有哪些積木、分類 |
| Workspace(工作區) | 使用者拖放積木的畫布 |
| Block 定義 | 積木的外觀與參數(欄位/輸入/連接) |
| Generator(生成器) | 積木 → 目標語言程式碼(forBlock) |
| Serialization | 儲存/載入積木(JSON/XML) |
一塊自訂積木由三種零件組成,理解它們才能設計出「好看又正確」的積木:
| 零件 | 作用 | 範例 |
|---|---|---|
| 欄位(Field) | 使用者可編輯的輸入 | 文字框、下拉選單、數字、勾選框 |
| 輸入(Input) | 可嵌入其他積木的「插槽」 | 值輸入(input_value)、語句輸入(input_statement)、虛擬輸入(input_dummy) |
| 連接(Connection) | 積木與其他積木相接的接頭 | output(值)、previous/next(語句堆疊) |
Blockly.common.defineBlocksWithJsonArray([{
type: 'say_hi',
message0: '%1', // %1 對應 args0 第 1 項
args0: [
{type: 'field_input', name: 'NAME', text: '世界'}
],
previousStatement: null,
nextStatement: null,
colour: 160,
tooltip: '說一句打招呼的話',
helpUrl: ''
}]);
Blockly.Blocks['say_hi'] = {
init: function() {
this.appendDummyInput()
.appendField('打招呼')
.appendField(new Blockly.FieldTextInput('世界'), 'NAME');
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setColour(160);
this.setTooltip('說一句打招呼的話');
}
};
定義積木的外觀之後,要告訴 Blockly「這塊積木產生什麼程式碼」——用 forBlock:
import {javascriptGenerator} from 'blockly/javascript';
javascriptGenerator.forBlock['say_hi'] = function(block, generator) {
// 讀取 NAME 欄位的值
const name = block.getFieldValue('NAME');
// 組出程式碼字串(注意跳脫引號與換行)
const code = 'console.log("你好,' + name + '!");\n';
return code; // statement 積木直接回傳字串
};
// 使用:Blockly.JavaScript.workspaceToCode(workspace)
// 產出:console.log("你好,世界!");
[code, order],語句積木回傳純字串——詳見 單元 21。Blockly.inject(div, config) 啟動,拿到 workspace。Blockly.JavaScript.workspaceToCode(workspace) 拿程式碼。<div id="blocklyDiv"></div>
<script>
const ws = Blockly.inject('blocklyDiv', {
toolbox: {kind: 'categoryToolbox', contents: [
{kind: 'category', name: '自訂', colour: '160', contents: [
{kind: 'block', type: 'say_hi',
fields: {NAME: 'OpenCode'}} // 拖出即預填
]}
]}
});
// 生成
const code = Blockly.JavaScript.workspaceToCode(ws);
console.log(code); // console.log("你好,OpenCode!");
</script>
目標:一個有「前進/後退/左轉」的迷你控制工具
1. toolbox 定義三個積木(各帶角度參數)
2. 生成器輸出到一組指令字串
3. 按下「執行」→ 依序播放指令(可串 Blockly Games 迷宮概念)
積木:move_forward(角度)→ 生成 "FORWARD 90"
move_backward(角度)→ 生成 "BACKWARD 90"
turn_left(角度)→ 生成 "TURN_LEFT 90"
完成標竿:使用者能拼出「前進→右轉→前進」走出迷宮。
動手:找一個 Blockly 官方範例,改 toolbox 加入「打招呼」積木,並讓它輸出 JS(記得用修正後的 forBlock 寫法)。