도구 상자에서 사용자가 블록을 얻을 수 있습니다. 일반적으로 작업공간의 한 쪽에 표시됩니다. 카테고리가 있을 때도 있고 없는 경우도 있습니다.
이 페이지에서는 도구 상자의 구조 (예: 포함된 카테고리 및 포함된 블록)를 지정하는 방법을 중점적으로 설명합니다. 도구 상자의 UI를 변경하는 방법에 관한 자세한 내용은 Blockly 도구 상자 맞춤설정 Codelab 및 2021 Toolbox API 대화를 참고하세요.
형식
Blockly를 사용하면 몇 가지 형식을 사용하여 도구 상자의 구조를 지정할 수 있습니다. 새로운 권장 형식은 JSON을 사용하고 이전 형식은 XML을 사용합니다.
위의 도구 상자를 지정할 수 있는 다양한 방법은 다음과 같습니다.
JSON
2020년 9월 출시부터 JSON을 사용하여 도구 상자를 정의할 수 있습니다.
var toolbox = {
"kind": "flyoutToolbox",
"contents": [
{
"kind": "block",
"type": "controls_if"
},
{
"kind": "block",
"type": "controls_whileUntil"
}
]
};
var workspace = Blockly.inject('blocklyDiv', {toolbox: toolbox});
XML
<xml id="toolbox" style="display: none">
<block type="controls_if"></block>
<block type="controls_whileUntil"></block>
</xml>
<script>
var workspace = Blockly.inject('blocklyDiv',
{toolbox: document.getElementById('toolbox')});
</script>
XML 문자열
var toolbox = '<xml>' +
'<block type="controls_if"></block>' +
'<block type="controls_whileUntil"></block>' +
'</xml>';
var workspace = Blockly.inject('blocklyDiv', {toolbox: toolbox});
카테고리
도구 상자의 블록은 카테고리별로 정리할 수 있습니다.
다음은 위의 도구 상자를 정의할 수 있는 방법입니다. 여기에는 각각 블록을 포함하는 두 가지 카테고리 ('컨트롤' 및 '로직')가 있습니다.
JSON
{
"kind": "categoryToolbox",
"contents": [
{
"kind": "category",
"name": "Control",
"contents": [
{
"kind": "block",
"type": "controls_if"
},
]
},
{
"kind": "category",
"name": "Logic",
"contents": [
{
"kind": "block",
"type": "logic_compare"
},
{
"kind": "block",
"type": "logic_operation"
},
{
"kind": "block",
"type": "logic_boolean"
}
]
}
]
}
XML
<xml id="toolbox" style="display: none">
<category name="Control">
<block type="controls_if"></block>
<category name="Logic">
<block type="logic_compare"></block>
<block type="logic_operation"></block>
<block type="logic_boolean"></block>
</category>
</xml>
중첩된 카테고리
카테고리는 다른 카테고리 내에 중첩될 수 있습니다. 여기에 2개의 최상위 카테고리 ('핵심'과 '맞춤')가 있으며, 두 번째에는 2개의 하위 카테고리가 포함되며 각 카테고리에는 블록이 포함됩니다.
카테고리에 하위 카테고리 and 블록을 모두 포함할 수 있습니다. 위의 예에서 'Custom'에는 2개의 하위 카테고리 ('이동'과 '회전')와 자체 블록 ('시작')이 있습니다.
JSON
{
"kind": "categoryToolbox",
"contents": [
{
"kind": "category",
"name": "Core",
"contents": [
{
"kind": "block",
"type": "controls_if"
},
{
"kind": "block",
"type": "logic_compare"
},
]
},
{
"kind": "category",
"name": "Custom",
"contents": [
{
"kind": "block",
"type": "start"
},
{
"kind": "category",
"name": "Move",
"contents": [
{
"kind": "block",
"type": "move_forward"
}
]
},
{
"kind": "category",
"name": "Turn",
"contents": [
{
"kind": "block",
"type": "turn_left"
}
]
}
]
}
]
}
XML
<xml id="toolbox" style="display: none">
<category name="Core">
<block type="controls_if"></block>
<block type="logic_compare"></block>
</category>
<category name="Custom">
<block type="start"></block>
<category name="Move">
<block type="move_forward"></block>
</category>
<category name="Turn">
<block type="turn_left"></block>
</category>
</category>
</xml>
동적 카테고리
동적 카테고리는 열 때마다 함수에 따라 동적으로 다시 채워지는 카테고리입니다.
등록된 문자열 키를 통해 카테고리를 함수와 연결할 수 있도록 하여 이를 제한적으로 지원합니다. 함수는 블록, 버튼, 라벨 등 카테고리 콘텐츠의 정의를 반환해야 합니다. 콘텐츠는 JSON 또는 XML로 지정할 수 있지만 JSON이 권장됩니다.
또한 함수가 타겟 작업공간을 매개변수로 제공하므로 동적 카테고리의 블록은 작업공간의 상태에 기반할 수 있습니다.
JSON
2021년 9월 출시부터 'blockxml'
를 사용하지 않고 블록의 상태를 지정할 수 있습니다.
// Returns an array of objects.
var coloursFlyoutCallback = function(workspace) {
// Returns an array of hex colours, e.g. ['#4286f4', '#ef0447']
var colourList = getPalette();
var blockList = [];
for (var i = 0; i < colourList.length; i++) {
blockList.push({
'kind': 'block',
'type': 'colour_picker',
'fields': {
'COLOUR': colourList[i]
}
});
}
return blockList;
};
// Associates the function with the string 'COLOUR_PALETTE'
myWorkspace.registerToolboxCategoryCallback(
'COLOUR_PALETTE', coloursFlyoutCallback);
이전 JSON
2021년 9월 출시 이전에는 'blockxml'
속성을 사용하여 블록의 상태를 지정해야 했습니다.
// Returns an array of objects.
var coloursFlyoutCallback = function(workspace) {
// Returns an array of hex colours, e.g. ['#4286f4', '#ef0447']
var colourList = getPalette();
var blockList = [];
for (var i = 0; i < colourList.length; i++) {
blockList.push({
'kind': 'block',
'type': 'colour_picker', // Type is optional if you provide blockxml
'blockxml': '<block type="colour_picker">' +
'<field name="COLOUR">' + colourList[i] + '</field>' +
'</block>'
});
}
return blockList;
};
// Associates the function with the string 'COLOUR_PALETTE'
myWorkspace.registerToolboxCategoryCallback(
'COLOUR_PALETTE', coloursFlyoutCallback);
XML
// Returns an arry of XML nodes.
var coloursFlyoutCallback = function(workspace) {
// Returns an array of hex colours, e.g. ['#4286f4', '#ef0447']
var colourList = getPalette();
var blockList = [];
for (var i = 0; i < colourList.length; i++) {
var block = document.createElement('block');
block.setAttribute('type', 'colour_picker');
var field = document.createElement('field');
field.setAttribute('name', 'COLOUR');
field.innerText = colourList[i];
block.appendChild(field);
blockList.push(block);
}
return blockList;
};
// Associates the function with the string 'COLOUR_PALETTE'
myWorkspace.registerToolboxCategoryCallback(
'COLOUR_PALETTE', coloursFlyoutCallback);
동적 카테고리 함수가 문자열 키 (등록됨)와 연결되면 이 문자열 키를 카테고리 정의의 custom
속성에 할당하여 카테고리를 동적으로 만들 수 있습니다.
JSON
{
"kind": "category",
"name": "Colours",
"custom": "COLOUR_PALETTE"
}
XML
<category name="Colours" custom="COLOUR_PALETTE"></category>
기본 제공 동적 카테고리
Blockly는 세 가지 동적 카테고리를 기본으로 제공합니다.
'VARIABLE'
는 유형이 지정되지 않은 변수의 카테고리를 만듭니다.'VARIABLE_DYNAMIC'
는 유형이 지정된 변수의 카테고리를 만듭니다. 문자열, 숫자, 색상을 만드는 버튼이 있습니다.'PROCEDURE'
는 함수 블록의 카테고리를 만듭니다.
JSON
{
"kind": "category",
"name": "Variables",
"custom": "VARIABLE"
},
{
"kind": "category",
"name": "Variables",
"custom": "VARIABLE_DYNAMIC"
},
{
"kind": "category",
"name": "Functions",
"custom": "PROCEDURE"
}
XML
<category name="Variables" custom="VARIABLE"></category>
<category name="Variables" custom="VARIABLE_DYNAMIC"></category>
<category name="Functions" custom="PROCEDURE"></category>
참고: 'procedure'라는 단어는 Blockly 코드베이스 전체에 사용되었지만 'function'이라는 단어는 학생들이 더 이해하기 쉽습니다. 불일치 문제로 불편을 드려 죄송합니다.
사용 중지
사용 중지된 카테고리는 사용자가 카테고리를 열 수 없으며 키보드 탐색 중에 건너뜁니다.
var category = toolbox.getToolboxItems()[0];
category.setDisabled('true');
카테고리가 사용 중지되면 'disabled'
속성이 DOM 요소에 추가되어 사용 중지된 카테고리의 모양을 제어할 수 있습니다.
.blocklyToolboxCategory[disabled="true"] {
opacity: .5;
}
숨기는 중
숨겨진 카테고리는 도구 상자의 일부로 표시되지 않습니다. 숨겨진 카테고리는 나중에 자바스크립트를 통해 표시할 수 있습니다.
JSON
{
"kind": "category",
"name": "...",
"hidden": "true"
}
XML
<category name="..." hidden="true"></category>
JavaScript
var category = toolbox.getToolboxItems()[0];
category.hide();
// etc...
category.show();
확장
이는 다른 중첩된 카테고리가 포함된 카테고리에만 적용됩니다.
카테고리가 펼쳐지면 하위 카테고리가 표시됩니다. 기본적으로 중첩된 카테고리는 접혀 있으며 확장하려면 클릭해야 합니다.
JSON
{
"kind": "category",
"name": "...",
"expanded": "true"
}
XML
<category name="..." expanded="true"></sep>
스타일
Blockly는 기본 카테고리 UI와 함께 몇 가지 기본 스타일 지정 옵션을 제공합니다. UI의 고급 스타일 지정/구성을 실행하는 방법에 관한 자세한 내용은 Blockly 도구 상자 맞춤설정 Codelab 및 2021 Toolbox API 소개를 참고하세요.
테마
테마를 사용하면 카테고리의 색상을 포함하여 작업공간의 모든 색상을 한 번에 지정할 수 있습니다.
이 속성을 사용하려면 카테고리를 특정 카테고리 스타일과 연결해야 합니다.
JSON
{
"kind": "category",
"name": "Logic",
"categorystyle": "logic_category"
}
XML
<category name="Logic" categorystyle="logic_category"></category>
색상
색상을 직접 지정할 수도 있지만 이 방법은 권장되지 않습니다. 색상은 색조를 지정하는 문자열화된 숫자 (0~360)입니다. 영국식 철자를 주의하세요.
JSON
{
"contents": [
{
"kind": "category",
"name": "Logic",
"colour": "210"
},
{
"kind": "category",
"name": "Loops",
"colour": "120"
}
]
}
XML
<xml id="toolbox" style="display: none">
<category name="Logic" colour="210">...</category>
<category name="Loops" colour="120">...</category>
<category name="Math" colour="230">...</category>
<category name="Colour" colour="20">...</category>
<category name="Variables" colour="330" custom="VARIABLE"></category>
<category name="Functions" colour="290" custom="PROCEDURE"></category>
</xml>
현지화 가능한 색상 참조 사용도 지원됩니다.
카테고리 CSS
더 강력한 맞춤설정을 원한다면 Blockly를 사용하면 기본 UI의 다양한 요소에 CSS 클래스를 지정할 수도 있습니다. 그런 다음 CSS를 사용해 스타일을 지정할 수 있습니다.
다음 요소 유형에는 CSS 클래스가 적용될 수 있습니다.
- container - 카테고리의 상위 div에 대한 클래스입니다. 기본값은
blocklyToolboxCategory
입니다. - row - 카테고리 라벨 및 아이콘이 포함된 div의 클래스입니다. 기본값은
blocklyTreeRow
입니다. - icon - 카테고리 아이콘의 클래스입니다. 기본값은
blocklyTreeIcon
입니다. - label - 카테고리 라벨의 클래스입니다. 기본값은
blocklyTreeLabel
입니다. - selected - 카테고리를 선택했을 때 카테고리에 추가되는 클래스입니다. 기본값은
blocklyTreeSelected
입니다. - openicon - 카테고리에 중첩된 카테고리가 있고 열려 있는 경우 아이콘에 추가되는 클래스입니다. 기본값은
blocklyTreeIconOpen
입니다. - closeicon - 카테고리에 중첩된 카테고리가 있고 닫힌 경우 아이콘에 추가되는 클래스입니다. 기본값은
blocklyTreeIconClosed
입니다.
두 형식 중 하나를 사용하여 클래스를 지정하는 방법은 다음과 같습니다.
JSON
cssConfig 속성을 사용하여 특정 요소 유형의 CSS 클래스를 설정합니다.
{
"kind": "category",
"name": "...",
"cssConfig": {
"container": "yourClassName"
}
}
XML
앞에 'css-'를 추가하여 특정 요소 유형의 CSS 클래스를 설정합니다.
<category name="..." css-container="yourClassName"></category>
액세스
프로그래매틱 방식으로 카테고리에 액세스하는 방법에는 두 가지가 있습니다. 색인으로 액세스할 수 있습니다 (여기에서 0이 최상위 카테고리임).
var category = toolbox.getToolboxItems()[0];
또는 ID별:
var category = toolbox.getToolboxItemById('categoryId');
도구 상자 정의에서 ID가 다음과 같이 지정됩니다.
JSON
{
"kind": "category",
"name": "...",
"toolboxitemid": "categoryId"
}
XML
<category name="..." toolboxitemid="categoryId"></category>
사전 설정 블록
도구 상자 정의에는 필드가 기본값으로 설정된 블록이나 이미 연결된 블록이 포함될 수 있습니다.
여기에는 네 가지 블록이 있습니다.
- 사전 설정 값이 없는 간단한
logic_boolean
블록:
- 기본값 0 대신 숫자 42를 표시하도록 수정된
math_number
블록:
- 3개의
math_number
블록이 연결된controls_for
블록:
- 두 개의
math_number
섀도우 블록이 연결된math_arithmetic
블록:
다음은 이러한 4개의 블록이 포함된 도구 상자 정의입니다.
JSON
2021년 9월 출시부터 'blockxml'
를 사용하여 블록 상태를 지정할 수 있습니다.
{
"kind": "flyoutToolbox",
"contents": [
{
"kind": "block",
"type": "logic_boolean"
},
{
"kind": "block",
"type": "math_number",
"fields": {
"NUM": 42
}
},
{
"kind": "block",
"type": "controls_for",
"inputs": {
"FROM": {
"block": {
"type": "math_number",
"fields": {
"NUM": 1
}
}
},
"TO": {
"block": {
"type": "math_number",
"fields": {
"NUM": 10
}
}
},
"BY": {
"block": {
"type": "math_number",
"fields": {
"NUM": 1
}
}
},
}
},
{
"kind": "block",
"type": "math_arithmetic",
"fields": {
"OP": "ADD"
},
"inputs": {
"A": {
"shadow": {
"type": "math_number",
"fields": {
"NUM": 1
}
}
},
"B": {
"shadow": {
"type": "math_number",
"fields": {
"NUM": 1
}
}
}
}
},
]
}
이전 JSON
2021년 9월 출시 이전에는 'blockxml'
속성을 사용하여 블록의 상태를 지정해야 했습니다.
{
"kind": "flyoutToolbox",
"contents": [
{
"kind": "block",
"type": "logic_boolean"
},
{
"kind": "block",
"blockxml":
'<block type="math_number">' +
'<field name="NUM">42</field>' +
'</block>'
},
{
"kind": "block",
"blockxml":
'<block type="controls_for">' +
'<value name="FROM">' +
'<block type="math_number">' +
'<field name="NUM">1</field>' +
'</block>' +
'</value>' +
'<value name="TO">' +
'<block type="math_number">' +
'<field name="NUM">10</field>' +
'</block>' +
'</value>' +
'<value name="BY">' +
'<block type="math_number">' +
'<field name="NUM">1</field>' +
'</block>' +
'</value>' +
'</block>'
},
{
"kind": "block",
"blockxml":
'<block type="math_arithmetic">' +
'<field name="OP">ADD</field>' +
'<value name="A">' +
'<shadow type="math_number">' +
'<field name="NUM">1</field>' +
'</shadow>' +
'</value>' +
'<value name="B">' +
'<shadow type="math_number">' +
'<field name="NUM">1</field>' +
'</shadow>' +
'</value>' +
'</block>'
},
]
}
XML
<xml id="toolbox" style="display: none">
<block type="logic_boolean"></block>
<block type="math_number">
<field name="NUM">42</field>
</block>
<block type="controls_for">
<value name="FROM">
<block type="math_number">
<field name="NUM">1</field>
</block>
</value>
<value name="TO">
<block type="math_number">
<field name="NUM">10</field>
</block>
</value>
<value name="BY">
<block type="math_number">
<field name="NUM">1</field>
</block>
</value>
</block>
<block type="math_arithmetic">
<field name="OP">ADD</field>
<value name="A">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
<value name="B">
<shadow type="math_number">
<field name="NUM">1</field>
</shadow>
</value>
</block>
</xml>
이러한 정의를 수작업으로 작성하는 일은... 조금 어려울 수 있습니다. 대신 블록을 작업공간에 로드한 후 다음 코드를 실행하여 정의를 가져올 수 있습니다. 이러한 호출이 작동하는 이유는 도구 상자가 직렬화 시스템과 동일한 블록 형식을 사용하기 때문입니다.
JSON
console.log(Blockly.serialization.workspaces.save(Blockly.getMainWorkspace()));
XML
console.log(Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace()));
x
, y
, id
속성은 도구 상자에서 무시되므로 삭제할 수도 있습니다.
그림자 블록
그림자 블록은 여러 기능을 실행하는 자리표시자 블록입니다.
- 상위 블록의 기본값을 나타냅니다.
- 이를 통해 사용자는 숫자나 문자열 블록을 가져오지 않고도 값을 직접 입력할 수 있습니다.
- 일반 블록과 달리 사용자가 블록 위에 블록을 떨어뜨리면 대체됩니다.
- 예상되는 가치 유형을 사용자에게 알려줍니다.
사용 중지된 차단
사용 중지된 블록은 도구 상자에서 드래그할 수 없습니다. 블록은 선택적 disabled
속성을 사용하여 개별적으로 사용 중지할 수 있습니다.
JSON
{
"kind": "flyoutToolbox",
"contents": [
{
"kind": "block",
"type":"math_number"
},
{
"kind": "block",
"type": "math_arithmetic"
},
{
"kind": "block",
"type": "math_single",
"disabled": "true"
}
]
}
XML
<xml id="toolbox" style="display: none">
<block type="math_number"></block>
<block type="math_arithmetic"></block>
<block type="math_single" disabled="true"></block>
</xml>
setEnabled
를 사용하여 프로그래매틱 방식으로 블록을 사용 중지하거나 사용 설정할 수도 있습니다.
변수 필드
변수 필드는 도구 상자에 있을 때와 단순히 직렬화할 때 다르게 지정해야 할 수 있습니다.
특히 변수 필드가 일반적으로 JSON으로 직렬화되면 변수가 나타내는 변수의 ID만 포함됩니다. 변수의 이름과 유형이 별도로 직렬화되기 때문입니다. 그러나 도구 상자에는 이러한 정보가 포함되어 있지 않으므로 변수 필드에 직접 포함해야 합니다.
{
"kind": "flyoutToolbox",
"content": [
{
"type": "controls_for",
"fields": {
"VAR": {
"name": "index",
"type": "Number"
}
}
}
]
}
구분자
두 카테고리 사이에 구분자를 추가하면 두 카테고리 사이에 선과 추가 공백이 생성됩니다.
JSON 또는 XML 도구 상자 정의에서 구분자의 클래스를 변경할 수 있습니다.
JSON
{
"kind": "sep",
"cssConfig": {
"container": "yourClassName"
}
}
XML
<sep css-container="yourClassName"></sep>
두 블록 사이에 구분자를 추가하면 블록 사이에 간격이 생깁니다. 기본적으로 모든 블록은 하단 이웃에서 24픽셀씩 떨어져 있습니다. 이 구분은 기본 간격을 대체하는 'gap' 속성을 사용하여 변경할 수 있습니다.
이렇게 하면 도구 상자에서 블록의 논리적 그룹을 만들 수 있습니다.
JSON
{
"kind": "flyoutToolbox",
"contents": [
{
"kind": "block",
"type":"math_number"
},
{
"kind": "sep",
"gap": "32"
},
{
"kind": "block",
"blockxml": "<block type='math_arithmetic'><field name='OP'>ADD</field></block>"
},
{
"kind": "sep",
"gap": "8"
},
{
"kind": "block",
"blockxml": "<block type='math_arithmetic'><field name='OP'>MINUS</field></block>"
}
]
}
XML
<xml id="toolbox" style="display: none">
<block type="math_number"></block>
<sep gap="32"></sep>
<block type="math_arithmetic">
<field name="OP">ADD</field>
</block>
<sep gap="8"></sep>
<block type="math_arithmetic">
<field name="OP">MINUS</field>
</block>
</xml>
버튼 및 라벨
도구 상자에서 블록을 배치할 수 있는 곳에 버튼이나 라벨을 배치할 수 있습니다.
JSON
{
"kind": "flyoutToolbox",
"contents": [
{
"kind": "block",
"type":"logic_operation"
},
{
"kind": "label",
"text": "A label",
"web-class": "myLabelStyle"
},
{
"kind": "label",
"text": "Another label"
},
{
"kind": "block",
"type": "logic_negate"
},
{
"kind": "button",
"text": "A button",
"callbackKey": "myFirstButtonPressed"
},
{
"kind": "block",
"type": "logic_boolean"
}
]
}
XML
<xml id="toolbox" style="display: none">
<block type="logic_operation"></block>
<label text="A label" web-class="myLabelStyle"></label>
<label text="Another label"></label>
<block type="logic_negate"></block>
<button text="A button" callbackKey="myFirstButtonPressed"></button>
<block type="logic_boolean"></block>
</xml>
<style>
.myLabelStyle>.blocklyFlyoutLabelText {
font-style: italic;
fill: green;
}
</style>
버튼 또는 라벨에 적용할 CSS 클래스 이름을 지정할 수 있습니다. 위의 예에서 첫 번째 라벨에서는 맞춤 스타일을 사용하고 두 번째 라벨에서는 기본 스타일을 사용합니다.
버튼에는 콜백 함수가 있어야 하며, 라벨은 있으면 안 됩니다. 특정 버튼 클릭에 대한 콜백을 설정하려면
yourWorkspace.registerButtonCallback(yourCallbackKey, yourFunction).
함수는 클릭된 버튼을 인수로 수락해야 합니다. 변수 카테고리의 '변수 만들기...' 버튼은 콜백이 있는 버튼의 좋은 예입니다.
도구 상자 변경
애플리케이션은 언제든지 단일 함수 호출을 통해 도구 상자에서 사용할 수 있는 블록을 변경할 수 있습니다.
workspace.updateToolbox(newTree);
초기 구성 중과 마찬가지로 newTree
는 노드 트리, 문자열 표현 또는 JSON 객체일 수 있습니다. 유일한 제한사항은 모드가 변경될 수 없다는 것입니다. 즉, 초기에 정의된 도구 상자에 카테고리가 있으면 새 도구 상자에도 카테고리가 있어야 합니다(카테고리는 변경될 수 있음). 마찬가지로 처음에 정의된 도구 상자에 카테고리가 없다면 새 도구 상자에는 어떤 카테고리도 없을 수 있습니다.
단일 카테고리의 콘텐츠는 다음과 같은 방법으로 업데이트할 수 있습니다.
var category = workspace.getToolbox().getToolboxItems()[0];
category.updateFlyoutContents(flyoutContents);
여기서 flyoutContents는 JSON, 노드 트리 또는 문자열 표현을 사용하여 정의된 블록 목록일 수 있습니다.
이때 도구 상자를 업데이트하면 일부 UI가 사소하게 재설정된다는 점에 유의하세요.
- 카테고리가 없는 도구 상자에서 사용자가 변경한 모든 필드 (예: 드롭다운)가 기본값으로 되돌아갑니다.
다음은 카테고리 및 블록 그룹이 포함된 트리의 실시간 데모입니다.