Zum Erstellen benutzerdefinierter Prozedurblöcke ist Folgendes erforderlich:
- Installieren Sie das Verfahren @blockly/block-shareable-procedures. wie unter Verwendung des Verfahrens beschrieben. Seite.
- Verwenden Sie das JSON-Serialisierungssystem, wie in der Übersicht erläutert. .
Datenmodelle zum Arbeitsbereich hinzufügen
Sowohl die Prozedurdefinition als auch die Prozeduraufruferblöcke verweisen auf eine Sicherungsdaten , das die Signatur der Prozedur definiert (Name, Parameter und Return). Dies ermöglicht mehr Flexibilität bei der Entwicklung Ihrer Anwendung (z.B. können Sie Verfahren in einem Arbeitsbereich definieren und in eine andere).
Dies bedeutet, dass Sie die Prozedurdatenmodelle dem Arbeitsbereich hinzufügen müssen damit Ihre Blöcke funktionieren. Dafür gibt es mehrere Möglichkeiten (z.B. Benutzeroberflächen).
Mit der Methode @blockly/block-shareable-procedures geschieht dies durch
die Erstellung ihrer unterstützenden Datenmodelle dynamisch in Blöcken für die Prozedurdefinition
wenn sie im Arbeitsbereich instanziiert werden. Um dies selbst zu implementieren,
das Modell in init
erstellen und in destroy
löschen.
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());
}
}
Informationen zu den Blockierungen zurückgeben
Ihre Prozedurdefinition und Ihre Prozeduraufrufblöcke müssen die
getProcedureModel
-, isProcedureDef
- und getVarModels
-Methoden. Dies sind die
Hooks Der Blockly-Code verwendet den Abruf von Informationen zu Ihren Prozedurblöcken.
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 [];
},
};
Erneutes Rendern bei Updates auslösen
Ihre Prozedurdefinition und Ihre Prozeduraufrufblöcke müssen die
doProcedureUpdate
-Methode. Dies ist der Aufhänger, den Datenmodelle aufrufen,
um sich selbst
wieder zu rendern.
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...
}
};
Benutzerdefinierte Serialisierung hinzufügen
Die Serialisierung von Prozedurblöcken muss zwei verschiedene Dinge bewirken.
- Beim Laden aus JSON müssen Ihre Blöcke einen Verweis auf ihre da die Blöcke und Modelle separat serialisiert werden.
- Beim Kopieren und Einfügen eines Prozedurblocks muss der Block serialisiert werden den gesamten Status seines Prozedurmodells, sodass es repliziert werden kann.
Beide Vorgänge werden über saveExtraState
und loadExtraState
abgewickelt.
Beachten Sie, dass benutzerdefinierte Prozedurblöcke nur unterstützt werden, wenn die JSON-Datei verwendet wird
Serialisierungssystem, sodass wir nur JSON-Serialisierungs-Hooks definieren müssen.
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();
}
}
}
};
Optional: Prozedurmodell ändern
Sie können auch die Möglichkeit für Benutzer hinzufügen, das Prozedurmodell zu ändern. Anrufen
insertParameter
, deleteParameter
oder setReturnTypes
Methoden
löst automatisch das erneute Rendern Ihrer Blöcke aus (über doProcedureUpdate
).
Zu den Optionen zum Erstellen von Benutzeroberflächen zum Ändern des Prozedurmodells gehören unter anderem die Verwendung von Mutators (die der Verwendung integrierter Prozedurblöcke), Image-Felder mit Klick-Handlern, vollständig außerhalb von Blockly usw. liegt.
Blöcke zur Toolbox hinzufügen
Die integrierte dynamische Prozedurkategorie von Blockly ist spezifisch für die in Blockly integrierte Prozedurblöcke. Um auf Ihre Blockierungen zugreifen zu können, müssen Sie also Ihre eigenen benutzerdefinierten dynamischen Creatives Kategorie und fügen Sie sie hinzu, zu Ihrer Toolbox hinzufügen.
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);