こんにちは!
EYSの中澤です。
システムサポート課で音楽教室を運営するシステムの課題対応、機能追加を行っています。
また、プログラミング教室のカリキュラムを考えています。
今回は、子供のプログラミング学習のみならず、IoTや非エンジニア向けのサービスで使用されているビジュアルプログラミング環境のつくりかたをまとめました。
数字の1〜9のブロックと足し算のブロックを作って計算結果を教えてくれる環境を作ります。
ScratchやMakeCodeのベースとなっているGoogleのオープンソースプロジェクトBlocklyをつかうことで、HTML, JavaScript, CSSのみで、GUI関連の処理を実装しなくても作れるようになっています。
ソース
https://github.com/google/blockly
ドキュメント
https://developers.google.com/blockly/
必要なファイルは blockly_compressed.js です。今回はCDNのファイルを参照します。
まず、数字の1のブロックを表示してみましょう。
以下の内容で、htmlファイルを作成します。
<meta charset=”UTF-8″> <title>たしざん</title> <script src=”https://cdn.jsdelivr.net/npm/blockly@3.20191014.3/blockly.min.js”></script> <div id=”canvas”></div> <xml xmlns=”https://developers.google.com/blockly/xml” id=”toolbox” style=”display: none”> <block type=”digit1″></block> </xml> <script> Blockly.Blocks.digit1 = { init: function (block) { this.jsonInit({ “type”: “digit1”, “message0”: “1”, “output”: “Number”, “colour”: 230, “tooltip”: “”, “helpUrl”: “” }) } } var workspace = Blockly.inject(‘canvas’, { toolbox: document.getElementById(‘toolbox’), zoom: { startScale: 1.5 } }) </script> |
作成したHTMLをブラウザで開くと、下記のように表示されます。
灰色部分(ツールボックスといいます)のブロックを右側にドラッグすることでブロックを並べることができます。
Blockly.Blocksにブロックを定義して、xmlタグ内に定義したブロックをblockタグで並べるとでツールボックに表示される仕組みです。
ブロックのプロパティは次のとおりです。
プロパティ | 説明 |
type | ブロックの種類ごとの名前で重複しないように 自由に設定できる |
message0 | ブロックに表示する内容 |
output | ブロックから出力される値の型 |
colour | ブロックの色0〜360で指定 (HSV色空間の色相を指定) |
tooltip | ブロックにカーソルを合わせた際に 表示される説明 |
helpUrl | ブロックを右クリックしてHelpを選ぶと表示される 説明ページのURL |
ブロックの大きさは Blockly.inject の第2引数で zoom.startScale で指定できます。
次に、同様にして、9までのブロックを追加します。
カラフルにしてみました。
次は足し算をするブロックを追加します。
Blockly.Blocks.addition = { init: function (block) { this.jsonInit({ “type”: “addition”, “message0”: “%1 たす %2”, “args0”: [ { “type”: “input_value”, “name”: “left_value”, “check”: “Number” }, { “type”: “input_value”, “name”: “right_value”, “check”: “Number” } ], “inputsInline”: true, “output”: “Number”, “colour”: 0, “tooltip”: “2つのすうじをたします”, “helpUrl”: “” }) } } |
足し算をするには足す数と足される数の2つをセットしなければなりません。
そのために、arg0というプロパティを用意して、2つの値を受け取る枠を定義します。これらを入力といいます。各入力のプロパティには type, name, checkがあります。
プロパティ | 設定できる値 | 説明 |
type | input_value | 1つの値の枠を作る |
input_statement | 複数のつなげたブロック用の枠を作る | |
input_dummy | 枠は作らず文字のみ表示するときに使う | |
name | ブロック内で固有の名前を自由に設定できる | |
check | 受け付ける値の方を指定(省略可) |
また、message0 を 「%1 たす %2 」としていますが、%1には1つ目の入力枠が設定され、%2には2つ目の入力枠が設定されます。
最後に結果を表示するブロックを追加します。
これで、足し算のプログラムをブロックで組めるようになりました。
あとは実行できるようにします。
実行するには、ブロックで作ったプログラムを実行可能なプログラムのソースコード(JavaScript等)に変換してから実行する形になります。
ただ、そうするためには、それぞれのブロックがどのようなソースコードに変換されるかを定義する必要があります。
たとえば1のブロックの定義は次のようになります。
Blockly.JavaScript.digit1 = function(block) { return [ ‘1’, Blockly.JavaScript.ORDER_NONE ] } |
全ブロックに対して、JavaScriptに変換する定義をつけ、実行ボタンと押したときの処理を作れば完成です。
じっこう(id=run)を押したときの処理は次のように書きます。
document.getElementById(‘run’).addEventListener(‘click’, function() { try { eval(Blockly.JavaScript.workspaceToCode(workspace)) } catch(e) { alert(e) } }) |
Blockly.JavaScript.workspaceToCode でブロックの内容をJavaScriptのプログラムに変換することができます。
Blocklyの仕組みを使えば、任意の処理を行うブロックを作って、任意のプログラミング言語に変換、実行することが可能です。
最後に全ソースコードを載せておきます。(addition.html)
<meta charset=”UTF-8″> <title>たしざん</title> <script src=”https://cdn.jsdelivr.net/npm/blockly@3.20191014.3/blockly.min.js”></script> <div id=”canvas”></div> <xml xmlns=”https://developers.google.com/blockly/xml” id=”toolbox” style=”display: none”> <block type=”addition”></block> <block type=”display”></block> <block type=”digit1″></block> <block type=”digit2″></block> <block type=”digit3″></block> <block type=”digit4″></block> <block type=”digit5″></block> <block type=”digit6″></block> <block type=”digit7″></block> <block type=”digit8″></block> <block type=”digit9″></block> </xml> <button id=”run” type=”button” style=”font-size:20pt; border-radius:1em; position:fixed; bottom: 1em; right: 1em”>じっこう</button> <div id=”dialog” style=”position:fixed;top:0;left:0;right:0;bottom:0;opacity:0.8;background-color:white;transition-duration:1s;color:black;font-size:20pt;text-align:center;padding-top:4em;z-index:9999999;display:none”></div> <script> for (var i = 1; i < 10; i++) { (function (j) { Blockly.Blocks[‘digit’ + j] = { init: function (block) { this.jsonInit({ “type”: “digit” + j, “message0”: j.toString(), “output”: “Number”, “colour”: j * 40, “tooltip”: “”, “helpUrl”: “” }) } } Blockly.JavaScript[‘digit’ + j] = function(block) { return [ j.toString(), Blockly.JavaScript.ORDER_NONE ] } })(i) } Blockly.Blocks.addition = { init: function (block) { this.jsonInit({ “type”: “addition”, “message0”: “%1 たす %2”, “args0”: [ { “type”: “input_value”, “name”: “left_value”, “check”: “Number” }, { “type”: “input_value”, “name”: “right_value”, “check”: “Number” } ], “inputsInline”: true, “output”: “Number”, “colour”: 0, “tooltip”: “2つのすうじをたします”, “helpUrl”: “” }) } } Blockly.JavaScript.addition = function(block) { var left_value = Blockly.JavaScript.valueToCode(block, ‘left_value’, Blockly.JavaScript.ORDER_NONE) || 0 var right_value = Blockly.JavaScript.valueToCode(block, ‘right_value’, Blockly.JavaScript.ORDER_NONE) || 0 return [ left_value + ‘ + ‘ + right_value, Blockly.JavaScript.ORDER_NONE ] } Blockly.Blocks.display = { init: function (block) { this.jsonInit({ “type”: “display”, “message0”: “%1 のけいさんけっか”, “args0”: [ { “type”: “input_value”, “name”: “value” } ], “colour”: 230, “tooltip”: “”, “helpUrl”: “” }) } } Blockly.JavaScript.display = function(block) { var value = Blockly.JavaScript.valueToCode(block, ‘value’, Blockly.JavaScript.ORDER_NONE) || 0 return “var e = document.getElementById(‘dialog’);e.textContent = ‘けいさんけっかは ‘ + (” + value + “) + ‘ です!’;e.style.display = ”” } var workspace = Blockly.inject(‘canvas’, { toolbox: document.getElementById(‘toolbox’), zoom: { startScale: 1.5 } }) document.getElementById(‘run’).addEventListener(‘click’, function() { try { eval(Blockly.JavaScript.workspaceToCode(workspace)) } catch(e) { alert(e) } }) document.getElementById(‘dialog’).addEventListener(‘click’, function(e) { e.target.style.display = ‘none’ }) </script> |
EYSではシステム開発だけではなく、プログラミング教育のオリジナル教材を作成しています。興味のある方はぜひご連絡ください。