אפשרויות גרירה בהתאמה אישית

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

יש מעט מאוד מקרים שבהם כדאי להוסיף רכיב חדש שניתן לגרירה ל-Blockly (למשל, התוסף multiselect או שינוי האופן שבו אובייקט קיים מטפל בגרירות), כי אי אפשר להוסיף אובייקטים חדשים שעברו עיבוד ל-Blockly. האובייקטים המעובדים היחידים שיכולים להיות במרחב עבודה הם בלוקים, בועות ותגובות במרחב העבודה.

תחומי אחריות

לרכיבים שניתן לגרור יש כמה תפקידים במהלך הגרירה:

הטמעה

כדי ליצור רכיב חדש שאפשר לגרור, צריך להטמיע את הממשקים IRenderedElement ו-IDraggable. כך Blockly יודע שהאובייקט גלוי ושאפשר לגרור אותו.

class MyDraggable extends IRenderedElement, IDraggable {}

החזרת רכיב ה-SVG הבסיסי

השיטה getRootSvg מחזירה את רכיב ה-svg הבסיסי (בדרך כלל group) שמכיל את כל שאר הרכיבים שמרכיבים את התצוגה של הרכיב שניתן לגרירה.

getSvgRoot() {
  return this.rootSvg;
}

החזרת ניידות

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

isMovable() {
  return true;
}

מיקום החזרה

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

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

getRelativeToSurfaceXY() {
  return this.loc;
}

התחלת גרירה

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

בנוסף, צריך לשנות את רכיבי ה-SVG כך שיוצבו בשכבת הגרירה של סביבת העבודה, כדי שיוצגו מעל כל רכיב אחר.

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

startDrag(e) {
  // Save the original location so we can revert the drag.
  this.startLoc = this.getRelativeToSurfaceXY();

  // Disable resizing the workspace for performance.
  this.workspace.setResizesEnabled(false);

  // Put the element on the drag layer.
  this.workspace.getLayerManager()?.moveToDragLayer(this);

  // Fire a drag event...

  // etc...
}

גרירה

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

drag(newLoc, e) {
  this.moveTo(newLoc);
}

ביטול גרירות

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

revertDrag() {
  // Move back to the position that was stored in `startDrag`.
  this.moveTo(this.startLoc);
}

סיום הגרירה

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

הפונקציה endDrag תמיד נקראת אחרי revertDrag אם revertDrag נקראת.

endDrag() {
  // Put the element back on its original layer (in this case BLOCK).
  this.workspace
    .getLayerManager()
    ?.moveOffDragLayer(this, Blockly.layers.BLOCK);

  // Allow the workspace to start resizing again.
  this.workspace.setResizesEnabled(true);
}

בחירה

הרכיב שנגרר נקבע לפי הרכיב שמסומן כשמזוהה גרירה.

ISelectable

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

class MyDraggable implements ISelectable {
  constructor(workspace) {
    this.id = Blockly.utils.idGenerator.genUid();
    this.workspace = workspace;
  }

  select() {
    // Visually indicate this draggable is selected.
  }

  unselect() {
    // Visually indicate this draggable is not selected.
  }
}

הגדרת הבחירה

אפשר להגדיר את הרכיב שנבחר באמצעות קריאה ל-Blockly.common.setSelected(). בדרך כלל כדאי לעשות את זה בתגובה לאירוע pointerdown מהמשתמש.

  constructor() {
    this.initSvg();

    Blockly.browserEvents.conditionalBind(
      this.getSvgRoot(),
      'pointerdown',
      this,
      () => Blockly.common.setSelected(this));
  }

תאימות

רכיב ה-draggable יכול להטמיע ממשקים נוספים כדי שיוכל ליצור אינטראקציה עם מערכות אחרות ב-Blockly.

פריטים שניתנים למחיקה

אפשר להטמיע את הממשק IDeleteable כדי לאפשר השלכה של רכיבים שניתן לגרור לפח האשפה או ליעדי מחיקה אחרים.

class MyDraggable implements IDeletable {
  isDeletable() {
    return true;
  }

  dispose() {
    // Dispose of any references to data or SVG elements.
  }

  setDeleteStyle() {
    // Visually indicate that the draggable is about to be deleted.
  }
}

ניתן להעתקה

אתם יכולים להטמיע את הממשק ICopyable כדי לאפשר העתקה של הרכיב הניתן לגרירה, ולהגדיר את הממשק IPaster כדי לאפשר הדבקה שלו.

מידע נוסף על העתקה והדבקה זמין במאמר בנושא העתקה והדבקה.