รูปร่างการเชื่อมต่อ

มีหลายวิธีที่คุณสามารถปรับแต่งรูปลักษณ์ของการเชื่อมต่อ โดยแต่ละวิธีจะมีความยากขึ้นเรื่อยๆ คุณทั้งหมดต้องสร้าง ตัวแสดงผลที่กำหนดเอง

มิติข้อมูลพื้นฐาน

การเชื่อมต่อกับมิติข้อมูลที่แตกต่างกัน

คุณจะปรับแต่งการเชื่อมต่อได้โดยเปลี่ยนความกว้างหรือความสูง โดยที่ยังรักษารูปร่างพื้นฐานไว้เหมือนเดิม วิธีการคือ คุณต้องสร้างคอมโพเนนต์ผู้ให้บริการคงที่ที่กำหนดเอง และลบล้างค่าคงที่บางอย่าง

โหมดแสดงภาพต่างๆ จะกำหนดและใช้ค่าคงที่ที่ต่างกัน ดังนั้นโปรดดูเอกสารอ้างอิงสำหรับซูเปอร์คลาส

สำหรับตัวแสดงผลพื้นฐาน คุณลบล้าง 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;
  }
}

รูปร่างพื้นฐาน

การเชื่อมต่อกับรูปร่างต่างๆ

คุณสามารถปรับแต่งการเชื่อมต่อโดยการลบล้างรูปร่างพื้นฐาน รูปร่างพื้นฐานจะมีความสูง ความกว้าง และเส้นทาง 2 เส้นทาง

แต่ละเส้นทางวาดรูปร่างเดียวกัน แต่มาจากปลายด้านตรงข้าม

รอยบากที่วาดจากทั้งสองทิศทาง

ซึ่งเป็นสิ่งจำเป็นเนื่องจากขณะที่ลิ้นชักลากเส้นโครงร่างของบล็อก จะเป็นการวาดเส้นเชื่อมต่อแต่ละประเภทในทั้ง 2 ทิศทาง ตัวอย่างเช่น เส้นเชื่อมต่อก่อนหน้าจะวาดจากซ้ายไปขวา แต่การเชื่อมต่อถัดไปจะมาจากขวาไปซ้าย คุณจึงต้องระบุเส้นทางสำหรับ ทั้ง 2 กรณีนี้

ทิศทางที่บล็อกถูกวาดเข้ามา

คุณลบล้างเมธอด makeNotch สำหรับการเชื่อมต่อถัดไปและก่อนหน้า รวมถึงเมธอด 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)]),
    };
  }
}

ดูข้อมูลเกี่ยวกับวิธีกำหนดสตริงเส้นทางได้ในเอกสารประกอบเส้นทาง SVG ของ MDN เนมสเปซ 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);
        }
      }
    }
  }
}