Blocklyの基本的な使い方
この記事ではビジュアルプログラミング言語の一つであるBlocklyの基本的な使い方を紹介します。
See the Pen
Blockly on CodePen by Imai (@imai1)
on CodePen.
ワークスペースの設置
ワークスペースとは、ブロックのツールボックスやコーディングを行う領域をまとめたウィジェットのことです。
このセクションでは、BlocklyのワークスペースをWebページに設置する方法を説明します。この記事ではCodePenの中にBlocklyを埋め込んでいますが、やり方は通常のHTML/JavaScriptでも同じです。
Blocklyのライブラリの読み込み
まずはBlocklyのライブラリを読み込みます。読み込む方法はいくつかありますが、この記事ではHTML内に下記のタグを設置しました。
<script src="https://unpkg.com/blockly/blockly.min.js"></script>
ワークスペースを注入するタグの作成
ワークスペースはいずれかのタグに紐づけて展開されます。HTML上でワークスペースを設置したい場所に以下のようなタグを配置してください。
<div id="blocklyDiv" style="height: 300px; width: 600px;"></div>
なお、Blockly側から参照するために、タグにはIDが必要です。
タグとワークスペースの紐づけ
最後に、JavaScriptでタグにワークスペースを注入します。
// 指定したIDのタグにワークスペース(Blocklyのウィジェット)を注入。 const workspace = Blockly.inject("blocklyDiv", {toolbox: toolbox});
なおtoolbox
とは、(デフォルトでは)ワークスペースの左側に設置されるブロックのパレットのことです。次のような形式で、エンドユーザに提供するブロックの一覧を定義します。
var toolbox = { "contents": [ { "kind": "block", "type": "math_number" }, { "kind": "block", "type": "math_arithmetic" }, { "kind": "block", "type": "text" }, { "kind": "block", "type": "text_print" }, { "kind": "block", "type": "string_length" }, ] }
string_length
は、後で紹介するカスタムブロックです。それ以外はBlocklyのライブラリに元々用意されているブロックです。
ここまでのコードで、ページ内にBlocklyのワークスペースを追加することができます。ブロックをドラッグ&ドロップで動かしたり組み合わせたりする機能も動作します。
ブロックの初期配置
ワークスペースに予めブロックを置いておくには、次のようなコードを記載します。
const startBlocksText = "<xml><block type=\"text_print\"></block></xml>"; const dom = Blockly.Xml.textToDom(startBlocksText); Blockly.Xml.domToWorkspace(dom, workspace);
ブロックで作成したプログラムの実行
Blocklyで作成したプログラム(ブロックの塊)は、何らかの別の言語のプログラムに変換することで計算や処理を実行します。例えば、text_print
ブロックをJavaScriptでalert(右側に接続されたブロックを変換したコード)
に変換する、などのようなイメージです。
カスタムブロックではブロック別・言語別に変換方法を定義する必要がありますが、Blocklyにデフォルトで用意されているブロックには典型的な言語への変換方法も定義済みです。
実際にブロックをコードに変換する場合には、Blockly.対象言語.workspaceToCode
メソッドを利用します。更に、文字列形式のコードを実行する部分と合わせて、冒頭の例では次のような関数を作りました。
// ワークスペースのブロックをコード化して実行。 function execute() { const code = Blockly.JavaScript.workspaceToCode(workspace); eval(code); }
この関数をHTML上のボタンと紐づけることで、ボタンを押下するたびにワークスペースのプログラムが実行されます。
<button onclick="execute()">実行</button>
カスタムブロックの作成
カスタムブロックの定義
ユーザ独自のブロックは、JavaScriptでBlockly.Blocks
に新しい要素を追加することで定義できます。
// ブロックの定義 Blockly.Blocks["string_length"] = { init: function() { this.appendValueInput("VALUE") .setCheck("String") .appendField("length of"); this.setOutput(true, "Number"); this.setColour(160); this.setTooltip("Returns number of letters in the provided text."); this.setHelpUrl("http://www.w3schools.com/jsref/jsref_length_string.asp"); } };
追加する要素のキー(ここではstring_length
)がtoolbox
などで使用するための識別子となります。
その他のブロックの形や色などはinit
メソッド内で設定します。詳細な設定方法は次のページで説明されています。
カスタムブロックのコード変換
カスタムブロックから特定の言語のコードへの変換処理を定義する場合は、Blockly.対象の言語[カスタムブロックの識別子]
に変換処理の関数を追加します。
// コード化の定義 Blockly.JavaScript['string_length'] = function(block) { codeOfLengthOf = Blockly.JavaScript.valueToCode(block, 'VALUE', Blockly.JavaScript.ORDER_ATOMIC); const code = `(${codeOfLengthOf}).length`; return [code, Blockly.JavaScript.ORDER_ATOMIC]; }
Blockly.JavaScript.valueToCode(block, 'VALUE', Blockly.JavaScript.ORDER_ATOMIC);
は、定義したカスタムブロックの入力パラメータであるVALUE
に接続されたブロックをコードに変換します。VALUE
は、ブロック定義時の.setCheck("String")
によって、文字列型に限定されています。よってこのコードに.length
を繋げれば、文字列の長さを返すコードが出来上がります。すなわち、「string_length」ブロックは入力された文字列の長さを返すブロックとして機能します。「text」や「text_print」と接続して動作を確認してみてください。
なお、VALUE
はエンドユーザには「length of」というラベルで認識されていますが、Blocklyのコード内部ではブロックの定義時にappendValueInput
に渡した文字列でパラメータを識別する必要があります。別々の文字列の場合は混乱しやすいので注意が必要です。