カスタム プロシージャ ブロックを作成するには、次のことを行う必要があります。
- @blockly/block-shareable-procedures をインストールします。 記載されているように、手順の使用手順 ページをご覧ください。
- 概要で説明されているように、JSON シリアル化システムを使用する ページをご覧ください。
ワークスペースにデータモデルを追加する
プロシージャ定義とプロシージャ呼び出し元ブロックの両方がバッキング データを参照する プロシージャのシグネチャ(名前、パラメータ、 。これにより、アプリケーションをより柔軟に設計できるようになります( 1 つのワークスペースで複数のプロシージャを定義して、 あります。
つまり、プロシージャ データモデルをワークスペースに追加する必要があります 確認しましょうこれにはさまざまな方法があります(例: UI など)が含まれます。
これは、@blockly/block-shareable-procedures によって実現されます。
プロシージャ定義ブロックでバッキング データモデルを動的に作成する
ワークスペースにインスタンス化されますこれを自分で実装するには
init
にモデルを作成し、destroy
で削除します。
import {ObservableProcedureModel} from '@blockly/block-shareable-procedures';
Blockly.Blocks['my_procedure_def'] = {
init: function() {
this.model = new ObservableProcedureModel('default name');
this.workspace.getProcedureMap().add(model);
// etc...
}
destroy: function() {
// (Optionally) Destroy the model when the definition block is deleted.
// Insertion markers reference the model of the original block.
if (this.isInsertionMarker()) return;
this.workpace.getProcedureMap().delete(model.getId());
}
}
ブロックに関する情報を返す
プロシージャ定義とプロシージャ コールのブロックでは、
getProcedureModel
、isProcedureDef
、getVarModels
の各メソッド。これらは
Blockly コードがプロシージャ ブロックに関する情報を取得するために使用するフック。
Blockly.Blocks['my_procedure_def'] = {
getProcedureModel() {
return this.model;
},
isProcedureDef() {
return true;
},
getVarModels() {
// If your procedure references variables
// then you should return those models here.
return [];
},
};
Blockly.Blocks['my_procedure_call'] = {
getProcedureModel() {
return this.model;
},
isProcedureDef() {
return false;
},
getVarModels() {
// If your procedure references variables
// then you should return those models here.
return [];
},
};
更新時に再レンダリングをトリガーする
プロシージャ定義とプロシージャ コールのブロックでは、
doProcedureUpdate
メソッドを使用します。これはデータモデルが
再レンダリングを行います。
Blockly.Blocks['my_procedure_def'] = {
doProcedureUpdate() {
this.setFieldValue('NAME', this.model.getName());
this.setFieldValue(
'PARAMS',
this.model.getParameters()
.map((p) => p.getName())
.join(','));
this.setFieldValue(
'RETURN', this.model.getReturnTypes().join(',');
}
};
Blockly.Blocks['my_procedure_call'] = {
doProcedureUpdate() {
// Similar to the def block above...
}
};
カスタム シリアル化を追加する
プロシージャ ブロックのシリアル化では、2 つの別々の処理を行う必要があります。
- JSON から読み込む場合、ブロックは変数への参照を取得する必要があります。 バッキング データ モデルを使用します。
- プロシージャ ブロックをコピーして貼り付ける場合は、ブロックをシリアル化する必要があります。 複製できるように、プロシージャ モデル全体の状態を保存する必要があります。
これらはどちらも saveExtraState
と loadExtraState
によって処理されます。
繰り返しになりますが、カスタム プロシージャ ブロックは、JSON 配列の
JSON シリアル化フックを定義するだけで済みます。
import {
ObservableProcedureModel,
ObservableParameterModel,
isProcedureBlock
} from '@blockly/block-shareable-procedures';
Blockly.Blocks['my_procedure_def'] = {
// When doFullSerialization is true, we should serialize the full state of
// the model.
saveExtraState(doFullSerialization) {
const state = Object.create(null);
state['procedureId']: this.model.getId();
if (doFullSerialization) {
state['name'] = this.model.getName();
state['parameters'] = this.model.getParameters().map((p) => {
return {name: p.getName(), p.getId()};
});
state['returnTypes'] = this.model.getReturnTypes();
// Flag for deserialization.
state['createNewModel'] = true;
}
return state;
},
loadExtraState(state) {
const id = state['procedureId']
const map = this.workspace.getProcedureMap();
if (map.has(id) && !state['createNewModel']) {
// Delete the existing model (created in init).
map.delete(this.model.getId());
// Grab a reference to the model we're supposed to reference.
this.model = map.get(id);
this.doProcedureUpdate();
return;
}
// There is no existing procedure model (we are likely pasting), so
// generate it from JSON.
this.model
.setName(state['name'])
.setReturnTypes(state['returnTypes']);
for (const [i, param] of state['parameters'].entries()) {
this.model.insertParameter(
i,
new ObservableParameterModel(
this.workspace, param['name'], param['id']));
}
this.doProcedureUpdate();
},
};
Blockly.Blocks['my_procedure_call'] = {
saveExtraState() {
return {
'procedureId': this.model.getId(),
};
},
loadExtraState(state) {
// Delete our existing model (created in init).
this.workspace.getProcedureMap().delete(model.getId());
// Grab a reference to the new model.
this.model = this.workspace.getProcedureMap()
.get(state['procedureId']);
if (this.model) this.doProcedureUpdate();
},
// Handle pasting after the procedure definition has been deleted.
onchange(event) {
if (event.type === Blockly.Events.BLOCK_CREATE &&
event.blockId === this.id) {
if(!this.model) { // Our procedure definition doesn't exist =(
this.dispose();
}
}
}
};
必要に応じてプロシージャモデルを変更する
ユーザーがプロシージャ モデルを変更できるようにすることもできます。発信中
insertParameter
、deleteParameter
、または setReturnTypes
メソッド
自動的にブロックの再レンダリングがトリガーされます(doProcedureUpdate
を使用)。
プロシージャ モデルを変更する UI を作成するオプションには、 ミューテーター( 組み込みプロシージャにより使用がブロックされているなど)、クリック ハンドラを含む画像フィールドなど、 Blockly など外部のサービスになります。
ツールボックスにブロックを追加する
Blockly の組み込み動的プロシージャのカテゴリは Blockly の組み込み関数に固有 使用します。そのため、ブロックにアクセスするには、 独自のカスタム ダイナミック category を選択し、そのカテゴリを 追加してください。
const proceduresFlyoutCallback = function(workspace) {
const blockList = [];
blockList.push({
'kind': 'block',
'type': 'my_procedure_def',
});
for (const model of
workspace.getProcedureMap().getProcedures()) {
blockList.push({
'kind': 'block',
'type': 'my_procedure_call',
'extraState': {
'procedureId': model.getId(),
},
});
}
return blockList;
};
myWorkspace.registerToolboxCategoryCallback(
'MY_PROCEDURES', proceduresFlyoutCallback);