צורות חיבור

יש מספר דרכים שבהן אפשר להתאים אישית את מראה החיבורים, כל אחת עם ברמת הקושי. בכולם נדרשת יצירה של כלי לעיבוד בהתאמה אישית.

מאפיינים בסיסיים

חיבורים עם מאפיינים שונים

אפשר להתאים אישית את החיבורים על ידי שינוי הרוחב או הגובה שלהם, בזמן ושומרים על אותה הצורה הבסיסית. בשביל זה צריך ליצור רכיב ספק קבוע בהתאמה אישית, ולעקוף חלק מהקבועים.

מעבדים שונים מגדירים קבועים שונים ומשתמשים בהם, לכן מסמכי עזר לכיתת העל שלך:

ברינדור הבסיסי, אפשר לשנות את הערכים של NOTCH_WIDTH וגם NOTCH_HEIGHT לחיבורים הבאים והקודמים, וגם TAB_WIDTH ו-TAB_HEIGHT לקלט ולפלט בחיבורים.

class CustomConstantProvider extends Blockly.blockRendering.ConstantProvider {
  constructor() {
    super();
    this.NOTCH_WIDTH = 20;
    this.NOTCH_HEIGHT = 10;
    this.TAB_HEIGHT = 8;
  }
}

צורות בסיסיות

חיבורים עם צורות שונות

אפשר להתאים אישית את החיבורים על ידי שינוי הצורה הבסיסית שלהם. צורות בסיסיות יש גובה, רוחב ו-שני נתיבים.

כל דרך משרטטת את אותה הצורה, אבל מהקצוות הנגדיים!

חריר משני הכיוונים

זה הכרחי מכיוון שחלונית ההזזה משרטטת את קווי המתאר של בלוק, הוא מושך כל סוג של חיבור בשני הכיוונים. לדוגמה, החיבורים הקודמים נמשכים משמאל לימין, אבל החיבורים הבאים נמשך מימין לשמאל. צריך לספק נתיבים של במקרים האלה.

הכיוון שאליו משורטט בלוק

אפשר לשנות את השיטה makeNotch עבור 'הבא' ו'הקודם' ואת ה-method makePuzzleTab לקלט חיבורי פלט.

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

כדאי לעיין במסמכי התיעוד של MDN SVG כדי לקבל מידע נוסף על האופן שבו כדי להגדיר מחרוזות נתיב. מרחב השמות Blockly.utils.svgPaths סופק בתור wrapper דק מסביב למחרוזות האלה כדי שיהיה קריא יותר.

צורות לבדיקות חיבור

חיבורים שונים עם צורות שונות

אפשר להתאים אישית את החיבורים על ידי שינוי הצורה בהתאם למצב של החיבור בדיקת חיבור.

כך ניתן ליצור צורות שונות כדי לייצג סוגי נתונים שונים. לדוגמה, מחרוזות יכולות להיות מיוצגות על ידי חיבורי משולשים, ערך בוליאני מיוצג על ידי חיבורים עגולים.

כדי לספק צורות שונות לבדיקות חיבור שונות, צריך לעקוף את השיטה shapeFor. הצורות המוחזרות צריכות להיות מאותחלות ב-init.

למידע על הסוגים השונים של צורות, ראו צורות בסיסיות. יש תמיכה בצורות.

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

קלט בהתאמה אישית

ניתן להתאים אישית צורות חיבור על ידי יצירת קלט מותאם אישית לחלוטין. הזה מתבצעת רק אם רוצים שחיבורים מסוימים ייראו שונים מאחרים, אבל לא רוצים שהוא תתבסס על בדיקת החיבור.

לדוגמה, אם רוצים שהכניסות של כמה מהקלטים של הערכים יתבצעו כמו קלט של הצהרה, אפשר ליצור קלט מותאם אישית כדי לתמוך בכך.

יצירת מחלקה לקלט מותאם אישית

מבצעים את השלבים ליצירת קלט מותאם אישית.

יצירת מודעה ניתנת למדידה

עליכם ליצור ערך מדידה כדי לייצג את הקלט המותאם אישית.

הקלט המותאם אישית הניתנות למדידה צריך לרשת Blockly.blockRendering.InputConnection אפשר לכלול גם את נתוני המדידה הנוספים שצריך כדי לשרטט את צורת הקלט.

export class CustomInputMeasurable extends Blockly.blockRendering.InputConnection {
  constructor(constants, input) {
    super(constants, input);

    // Any extra measurement data...
  }
}

יצירת סרטונים ניתנים למדידה

פרטי העיבוד שלכם צריכים ליצור את האובייקט בהתאמה אישית ניתן למדידה. כדי לעשות את זה, תצטרכו לשנות את השיטה 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);
  }
}

אפשר ליצור שורה

כברירת מחדל, קלט לא יוצר שורות חדשות. אם אתם רוצים שהקלט כדי להפעיל את סוף השורה, צריך לעקוף את הפונקציה shouldStartNewRow_ פרטי רינדור.

export class RenderInfo extends Blockly.blockRendering.RenderInfo {
  shouldStartNewRow_(currInput, prevInput) {
    if (prevInput instanceof CustomInput) return true;
    return super.shouldStartNewRow_(currInput, prevInput);
  }
}

אפשר גם ליצור צורה לקלט

כדאי לאחסן את צורת הקלט באופן קבוע, בדיוק כמו שיש לנו בשביל חריצים וכרטיסיות של חידות. כך הקוד נשמר בצורה מסודרת שיהיה קל יותר לשנות אותה מאוחר יותר.

צייר את הקלט

לסיום, צריך לשנות את המגירה כדי לשרטט את הצורה.

מקורות קלט מותאמים אישית יכולים:

  • להשפיע על קווי המתאר של הבלוק, כמו קלט של הצהרות

    תמונה של קלט מתאר

  • אפשרות אחרת היא להשפיע על הרכיבים הפנימיים של הבלוק, כמו כניסות ערכים בתוך השורה

    תמונה של קלט פנימי

אם הקלט משפיע על קווי המתאר של הבלוק, מבטלים את השינוי drawOutline_, אחרת, לשנות 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);
        }
      }
    }
  }
}