أشكال الاتصال

هناك العديد من الطرق التي يمكنك من خلالها تخصيص الطرق التي تبدو بها عمليات الربط، ولكل طريقة منها زيادة الصعوبة. تتطلب جميعها إنشاء عارض مخصّص

السمات الأساسية

اتصالات ذات أبعاد مختلفة

يمكنك تخصيص الاتصالات عن طريق تغيير عرضها أو ارتفاعها، مع الحفاظ على نفس الشكل الأساسي. للقيام بذلك، تحتاج إلى إنشاء المكوِّن الثابت المخصص، وإلغاء بعض الثوابت.

وتعمل برامج العرض المختلفة على تحديد ثوابت مختلفة واستخدامها، لذا يُرجى مراجعة الوثائق المرجعية للصف المتميز:

بالنسبة إلى العارض الأساسي، يمكنك إلغاء 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 في الطريقة التالية والسابقة. والاتصالات، وطريقة 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 كغلاف رفيع حول هذه السلاسل لتسهيل قراءتها.

أشكال لعمليات التحقق من الاتصال

روابط مختلفة بأشكال مختلفة

يمكنك تخصيص الاتصالات من خلال تغيير الشكل بناءً على روابط التحقق من الاتصال.

يتيح لك هذا إنشاء أشكال مختلفة لتمثيل أنواع بيانات مختلفة. على سبيل المثال، يمكن تمثيل السلاسل باتصالات مثلثية، بينما يتم تمثيل القيم المنطقية بواسطة الاتصالات الدائرية.

لتوفير أشكال مختلفة لعمليات التحقق المختلفة من الاتصال، يجب إلغاء الطريقة 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);
        }
      }
    }
  }
}