Esistono diversi modi per personalizzare l'aspetto delle connessioni, ognuno con una difficoltà crescente. Tutti richiedono la creazione di un renderer personalizzato.
Dimensioni di base
Puoi personalizzare le connessioni modificando la larghezza o l'altezza, mantenendo al contempo la stessa forma di base. A questo scopo, devi creare un componente personalizzato di provider costante e sostituire alcune costanti.
I diversi renderer definiscono e utilizzano costanti diverse, quindi consulta la documentazione di riferimento per la tua superclasse:
Per il renderer di base, puoi sostituire NOTCH_WIDTH
e NOTCH_HEIGHT
per le connessioni successive e precedenti e TAB_WIDTH
e TAB_HEIGHT
per le connessioni di input e di output.
class CustomConstantProvider extends Blockly.blockRendering.ConstantProvider {
constructor() {
super();
this.NOTCH_WIDTH = 20;
this.NOTCH_HEIGHT = 10;
this.TAB_HEIGHT = 8;
}
}
Forme di base
Puoi personalizzare le connessioni sostituendo la forma di base. Le forme di base hanno altezza, larghezza e due percorsi.
Ogni percorso traccia la stessa forma, ma parte da estremità opposte.
Questo è necessario perché il riquadro a scomparsa traccia il contorno del blocco, disegna ogni tipo di connessione in entrambe le direzioni. Ad esempio, le connessioni precedenti vengono tracciate da sinistra a destra, mentre quelle successive vengono tracciate da destra a sinistra. Quindi devi fornire percorsi per entrambi i casi.
Puoi eseguire l'override del metodo makeNotch
per le connessioni successive e precedenti e del metodo makePuzzleTab
per le connessioni di input e di output.
class CustomConstantProvider extends Blockly.blockRendering.ConstantProvider {
makePuzzleTab() {
const width = this.TAB_WIDTH;
const height = this.TAB_HEIGHT;
return {
type: this.SHAPES.PUZZLE,
width,
height,
pathUp: Blockly.utils.svgPaths.line([
Blockly.utils.svgPaths.point(-width, -height / 2),
Blockly.utils.svgPaths.point(width, -height / 2)]),
pathDown: Blockly.utils.svgPaths.line([
Blockly.utils.svgPaths.point(-width, height / 2),
Blockly.utils.svgPaths.point(width, height / 2)]),
};
}
}
Consulta la documentazione relativa ai percorsi MDN SVG per informazioni su come definire le stringhe del percorso. Lo spazio dei nomi Blockly.utils.svgPaths
viene fornito
come un wrapper sottile intorno a queste stringhe per renderle più leggibili.
Forme per i controlli della connessione
Puoi personalizzare le connessioni modificando la forma in base al controllo della connessione della connessione.
In questo modo puoi creare forme diverse per rappresentare diversi tipi di dati. Ad esempio, le stringhe potrebbero essere rappresentate da connessioni triangolari, mentre i booleani sono rappresentati da connessioni rotonde.
Per fornire forme diverse per controlli di connessione diversi, devi sostituire il metodo shapeFor
. Le forme restituite dovrebbero essere inizializzate in init
.
Vedi le forme di base per informazioni sui tipi di forme supportati.
export class ConstantProvider extends Blockly.blockRendering.BaseConstantProvider {
shapeFor(connection) {
let check = connection.getCheck();
// For connections with no check, match any child block.
if (!check && connection.targetConnection) {
check = connection.targetConnection.getCheck();
}
if (check && check.includes('String')) return this.TRIANGULAR_TAB;
if (check && check.includes('Boolean')) return this.ROUND_TAB;
return super.shapeFor(connection);
}
}
Input personalizzati
Puoi personalizzare le forme di connessione creando un input completamente personalizzato. Questa operazione viene eseguita solo se vuoi che alcune connessioni abbiano un aspetto diverso da altre, ma non vuoi che siano basate sul controllo della connessione.
Ad esempio, se vuoi che alcuni input di valori siano rientrati come input delle istruzioni, puoi creare un input personalizzato a supporto di questa operazione.
Crea una classe di input personalizzata
Segui i passaggi per la creazione di un input personalizzato.
Crea una metrica
Devi creare una metrica misurabile per rappresentare il tuo input personalizzato.
Il tuo input personalizzato misurabile deve ereditare da Blockly.blockRendering.InputConnection
. Può anche includere
qualsiasi dato di misurazione aggiuntivo necessario per tracciare la forma dell'input.
export class CustomInputMeasurable extends Blockly.blockRendering.InputConnection {
constructor(constants, input) {
super(constants, input);
// Any extra measurement data...
}
}
Crea l'istanza di un elemento misurabile
Le tue informazioni di rendering devono creare un'istanza del tuo parametro misurabile
personalizzato. Per farlo, devi eseguire l'override del metodo addInput_
.
export class RenderInfo extends Blockly.blockRendering.RenderInfo {
addInput_(input, activeRow) {
if (input instanceof CustomInput) {
activeRow.elements.push(new CustomInputMeasurable(this.constants_, input));
}
super.addInput_(input, activeRow);
}
}
Se vuoi, puoi creare una riga
Per impostazione predefinita, gli input non creano nuove righe. Se vuoi che l'input attivi la fine di una riga, devi sostituire il metodo shouldStartNewRow_
delle informazioni di rendering.
export class RenderInfo extends Blockly.blockRendering.RenderInfo {
shouldStartNewRow_(currInput, prevInput) {
if (prevInput instanceof CustomInput) return true;
return super.shouldStartNewRow_(currInput, prevInput);
}
}
Se vuoi, puoi creare una forma per l'input
Ti consigliamo di memorizzare costantemente la forma dell'input, proprio come facciamo per le tacche e le schede dei rompicapi. Così il codice è organizzato in modo da essere più facile modificarlo in un secondo momento.
Inserisci l'input
Infine, devi modificare il cassetto per disegnare la forma.
Gli input personalizzati possono:
Influisce sul contorno del blocco, ad esempio sulle istruzioni inserite
Oppure influisce sugli elementi interni del blocco, ad esempio gli input di valori in linea
Se l'input influisce sulla struttura del blocco, esegui l'override di drawOutline_
, altrimenti esegui l'override di drawInternals_
.
export class Drawer extends Blockly.blockRendering.Drawer {
drawOutline_() {
this.drawTop_();
for (let r = 1; r < this.info_.rows.length - 1; r++) {
const row = this.info_.rows[r];
// Insert checks for your input here!
if (row.getLastInput() instanceof CustomInputMeasurable) {
this.drawCustomInput(row);
} else if (row.hasJaggedEdge) {
this.drawJaggedEdge_(row);
} else if (row.hasStatement) {
this.drawStatementInput_(row);
} else if (row.hasExternalInput) {
this.drawValueInput_(row);
} else {
this.drawRightSideRow_(row);
}
}
this.drawBottom_();
this.drawLeft_();
}
protected drawInternals_() {
for (const row of rows) {
for (const elem of row) {
// Insert checks for your input here!
if (elem instanceof CustomInputMeasurable) {
this.drawCustomInput(elem);
}
if (Types.isInlineInput(elem)) {
this.drawInlineInput_(elem as InlineInput);
} else if (Types.isIcon(elem) || Types.isField(elem)) {
this.layoutField_(elem as Field | Icon);
}
}
}
}
}