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

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

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

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

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

โหมดแสดงภาพที่แตกต่างกันจะกำหนดและใช้ค่าคงที่ที่แตกต่างกัน ดังนั้นลองดู เอกสารอ้างอิงสำหรับชั้นเรียนระดับสูงของคุณ:

สําหรับโหมดแสดงภาพพื้นฐาน คุณสามารถลบล้าง 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)]),
    };
  }
}

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