本章では、VUEのシンプルなサンプルで、BlocklyのBlockから生成コードを非同期的に実行する方法を説明しております。
Blocklyのコードをステップ毎に実行する時は、Interpreterライブラリをよく使っているんですけど、Interpreterライブラリを使いたくない場合は、JavaScriptのeval関数でBlocklyのコードを実行することも可能です。
evalは一般的に同期でソースコードを実行されているんで、非同期的に実行したい場合はどうしたらよいかについてのことを、以下のサンプルで説明して見ましょう。
事前準備
Blockly
公式サイト:https://developers.google.com/blockly/
Web版の資材:https://developers.google.com/blockly/guides/get-started/web#get_the_code
VUE
サンプル
testblock.js
このファイルで、画面表示用のブロックを作成します
BlocklyのDevelopToolから生成することができます。
Blockly.Blocks['block_asyncplay'] = {
init: function() {
this.appendStatementInput("MUSIC")
.setCheck(null)
.setAlign(Blockly.ALIGN_RIGHT)
.appendField("play");
this.setInputsInline(true);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(120);
this.setTooltip("");
this.setHelpUrl("");
}
};
Blockly.JavaScript['block_asyncplay'] = function(block) {
var statements_music = Blockly.JavaScript.statementToCode(block, 'MUSIC');
var code = "async function asyncplay() {\n" + statements_music + "\n}\n";
return code;
};
Blockly.Blocks['block_play'] = {
init: function() {
this.appendDummyInput()
.setAlign(Blockly.ALIGN_RIGHT)
.appendField("play");
this.setInputsInline(true);
this.setPreviousStatement(true, "String");
this.setNextStatement(true, "String");
this.setColour(120);
this.setTooltip("");
this.setHelpUrl("");
}
};
Blockly.JavaScript['block_play'] = function(block) {
var code = "await play(1000);\n";
return code;
};
test01.html
画面にブロックを表示するためのHTMLファイルです。
<script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.22/vue.min.js'></script><!-- 2019-01-25 https://cdnjs.com/libraries/vue -->
<script src="../blockly-master/blockly_compressed.js"></script>
<script src="../blockly-master/blocks_compressed.js"></script>
<script src="../blockly-master/javascript_compressed.js"></script>
<script src="../blockly-master/msg/js/en.js"></script>
<script src="./testblock.js"></script>
<body>
<div id="vue_example"></div>
<script>
var vue_example = new Vue({
el: '#vue_example',
template: `<div>
<div width="600px" height="50px">
<button v-on:click="test()">test</button>
</div>
<div width="600px" height="600px">
<div id="blocklyDiv" style="height: 100%; width: 100%;"></div>
<xml id="toolbox" ref="toolbox" style="display: none">
<block type="block_asyncplay"></block>
<block type="block_play"></block>
</xml>
<xml id="workbox" ref="workbox">
<block type="block_asyncplay" id="id_block_asyncplay" x="10" y="30">
<statement name="MUSIC">
<block type="block_play" id="id_block_play_01">
<next>
<block type="block_play" id="id_block_play_02">
<next>
<block type="block_play" id="id_block_play_03"></block>
</next>
</block>
</next>
</block>
</statement>
</block>
</xml>
</div>
</div>`,
data: {
message: 'Hello Vue.js!',
},
mounted() {
var workbox = this.$refs["workbox"];
var options = {
toolbox: toolbox,
collapse: true,
comments: true,
disable: true,
maxBlocks: Infinity,
trashcan: true,
horizontalLayout: false,
toolboxPosition: 'start',
css: true,
rtl: false,
scrollbars: true,
sounds: true,
oneBasedIndex: true,
grid: {
spacing: 20,
length: 1,
colour: '#888',
snap: true
}
}
/* Inject your workspace */
this.workspace = Blockly.inject('blocklyDiv', options)
//Workspaceに書かれたBlocksを表示
Blockly.Xml.domToWorkspace(workbox, this.workspace);
},
methods: {
test: function () {
var dom = Blockly.Xml.workspaceToDom(this.workspace);
console.log( Blockly.Xml.domToText(dom));
var code = Blockly.JavaScript.workspaceToCode(this.workspace);
console.log( code );
eval(code);
asyncplay();
async function play(waittime) {
return new Promise((resolve, reject) => {
console.log("play waittime:" + waittime);
setTimeout(resolve, waittime, 'time signature');
});
}
},
},
})
</script>
</body>
</html>