Forme di connessione

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

Connessioni con dimensioni diverse

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

connessioni con forme diverse

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.

una tacca tracciata da entrambe le direzioni

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.

la direzione in cui viene disegnato un blocco

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

connessioni con forme diverse

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

    immagine degli input di Outline

  • Oppure influisce sugli elementi interni del blocco, ad esempio gli input di valori in linea

    immagine degli input interni

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);
        }
      }
    }
  }
}