前言
因为之前我在网上找blockly变形器的相关的内容的时候,资料少的又少,现在我也来补充一点
版本
使用的blackly版本为12.1.0,如果为过于老的版本可能不适用
效果展示
可以根据我们的需要来进行切换样式
实现解释
通过在代码块的样式中添加setMutator为打开变形器的开关,打开后
this.setMutator(new Blockly.icons.MutatorIcon(['custom_if_elseif', 'custom_if_else'], this));
与之配合的是下面两个函数: decompose 用户点击变形器按钮时 展示当前结构供用户编辑 compose 用户完成编辑关闭窗口 根据编辑内容修改 block 结构
decompose: function (workspace) {
// 创建一个新的workspac,并且在这个workspace上面添加一个新块,名为custom_if_container
const containerBlock = workspace.newBlock('custom_if_container');
containerBlock.initSvg();
let connection = containerBlock.getInput('STACK').connection;
// 根据之前变形的结构,补充所存在的custom_if_elseif块和custom_if_else块
for (let i = 1; i <= this.elseifCount_; i++) {
const elseifBlock = workspace.newBlock('custom_if_elseif');
elseifBlock.initSvg();
connection.connect(elseifBlock.previousConnection);
connection = elseifBlock.nextConnection;
}
if (this.elseCount_) {
const elseBlock = workspace.newBlock('custom_if_else');
elseBlock.initSvg();
connection.connect(elseBlock.previousConnection);
}
return containerBlock;
},
// 每次放置新的块的时候进行变形的操作
compose: function (containerBlock) {
// 移除所有 elseif 和 else
for (let i = 1; this.getInput(`IF${i}`); i++) {
this.removeInput(`IF${i}`);
this.removeInput(`DO${i}`);
}
if (this.getInput('ELSE')) {
this.removeInput('ELSE');
}
// 用于记录这个块中存在的custom_if_elseif块和custom_if_else块的数量
this.elseifCount_ = 0;
this.elseCount_ = 0;
// 重新插入
let clauseBlock = containerBlock.getInputTargetBlock('STACK');
let i = 1;
// 根据取到的clauseBlock ,也就是打开变形器的这个工作区上面放置的块,进行添加并且记录数量
while (clauseBlock) {
if (clauseBlock.type === 'custom_if_elseif') {
this.appendValueInput(`IF${i}`)
.setCheck("Boolean")
.appendField("否则如果");
this.appendStatementInput(`DO${i}`)
.appendField("那么");
i++;
this.elseifCount_++;
} else if (clauseBlock.type === 'custom_if_else') {
this.appendStatementInput('ELSE')
.appendField("否则");
this.elseCount_++;
}
clauseBlock = clauseBlock.nextConnection && clauseBlock.nextConnection.targetBlock();
}
}
};
完整代码
Blockly.Blocks['custom_if'] = {
init: function () {
this.setMutator(new Blockly.icons.MutatorIcon(['custom_if_elseif', 'custom_if_else'], this));
this.appendValueInput("IF0")
.setCheck("Boolean")
.appendField("如果");
this.appendStatementInput("DO0")
.appendField("那么");
this.elseifCount_ = 0;
this.elseCount_ = 0;
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour("#1E90FF");
},
decompose: function (workspace) {
const containerBlock = workspace.newBlock('custom_if_container');
containerBlock.initSvg();
let connection = containerBlock.getInput('STACK').connection;
for (let i = 1; i <= this.elseifCount_; i++) {
const elseifBlock = workspace.newBlock('custom_if_elseif');
elseifBlock.initSvg();
connection.connect(elseifBlock.previousConnection);
connection = elseifBlock.nextConnection;
}
if (this.elseCount_) {
const elseBlock = workspace.newBlock('custom_if_else');
elseBlock.initSvg();
connection.connect(elseBlock.previousConnection);
}
return containerBlock;
},
compose: function (containerBlock) {
// 移除所有 elseif 和 else
for (let i = 1; this.getInput(`IF${i}`); i++) {
this.removeInput(`IF${i}`);
this.removeInput(`DO${i}`);
}
if (this.getInput('ELSE')) {
this.removeInput('ELSE');
}
this.elseifCount_ = 0;
this.elseCount_ = 0;
// 重新插入
let clauseBlock = containerBlock.getInputTargetBlock('STACK');
let i = 1;
while (clauseBlock) {
if (clauseBlock.type === 'custom_if_elseif') {
this.appendValueInput(`IF${i}`)
.setCheck("Boolean")
.appendField("否则如果");
this.appendStatementInput(`DO${i}`)
.appendField("那么");
i++;
this.elseifCount_++;
} else if (clauseBlock.type === 'custom_if_else') {
this.appendStatementInput('ELSE')
.appendField("否则");
this.elseCount_++;
}
clauseBlock = clauseBlock.nextConnection && clauseBlock.nextConnection.targetBlock();
}
}
};
Blockly.Blocks['custom_if_container'] = {
init: function () {
this.appendDummyInput().appendField("条件分支");
this.appendStatementInput("STACK");
this.setColour(210);
this.setTooltip("");
this.contextMenu = false;
}
};
Blockly.Blocks['custom_if_elseif'] = {
init: function () {
this.appendDummyInput().appendField("添加 否则如果");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(210);
this.setTooltip("");
this.contextMenu = false;
}
};
Blockly.Blocks['custom_if_else'] = {
init: function () {
this.appendDummyInput().appendField("添加 否则");
this.setPreviousStatement(true, null);
this.setColour(210);
this.setTooltip("");
this.contextMenu = false;
}
};
javascriptGenerator.forBlock['custom_if'] = function (block, generator) {
let code = '';
let n = 0;
const condition = generator.valueToCode(block, 'IF0', Order.NONE) || 'false';
const branch = generator.statementToCode(block, 'DO0');
code += `if (${condition}) {${branch}}`;
for (n = 1; n <= block.elseifCount_; n++) {
const condition = generator.valueToCode(block, 'IF' + n, Order.NONE) || 'false';
const branch = generator.statementToCode(block, 'DO' + n);
code += ` else if (${condition}) {${branch}}`;
}
if (block.elseCount_) {
const branch = generator.statementToCode(block, 'ELSE');
code += ` else {${branch}}`;
}
return code + '';
};