גורר הוא אובייקט של בקר שמרכז את משיכת רכיבים שניתן לגרור בתגובה לאינטראקציות של משתמשים.
יש מעט מאוד מקרים שבהם כדאי להטמיע גורם גרירה בהתאמה אישית, כי אין הרבה דברים שתרצו להתאים אישית בנוגע לתיאום של גרירה. התוסף scroll-options מטמיע רכיב גרירה מותאם אישית כי הוא רוצה להוסיף גלילה בקצה של סביבת העבודה, וכך לשנות את האופן שבו קואורדינטות הפיקסלים מומרות לקווי הרוחב והאורך של סביבת העבודה.
תחומי אחריות
למשתמש שגורר יש כמה אחריויות בזמן ביצוע גרירה:
- קריאה לשיטות גרירה על הרכיב שניתן לגרירה.
- חישוב המיקום שאליו צריך להעביר את האובייקט שניתן לגרירה לפי קואורדינטות של מרחב העבודה.
- קריאה לשיטות של יעד גרירה בכל יעדי גרירה שמוצגים מעליהם עכבר.
הטמעה
כדי ליצור רכיב גרירה בהתאמה אישית, צריך להטמיע את הממשק IDragger.
class MyDragger implements IDragger {
// Takes in the draggable being dragged and the workspace the drag
// is occurring in.
constructor(draggable, workspace);
}
אפשר גם ליצור תת-סוג של Blockly.dragging.Dragger המובנה, שכבר מטפל במשימות הבסיסיות.
התחלת גרירה
השיטה onDragStart מפעילה גרירה. הוא אמור לאחסן את כל הנתונים הנדרשים לביצוע הגרירת הרכיב. צריך גם להפעיל את startDrag על האובייקט הניתן לגרירה שנגרר.
onDragStart(e) {
this.startLoc = this.draggable.getRelativeToSurfaceXY();
this.draggable.startDrag(e);
}
גרירה
השיטה onDrag מבצעת גרירה. הוא אמור לחשב את המיקום החדש של הרכיב שניתן לגרירה בסביבת העבודה על סמך הערך של totalDelta, שמצוין בקואורדינטות פיקסלים.
הוא אמור לעדכן גם את כל יעדי הגרירה שמתרחשים מעליהם.
- תמיד צריך לקרוא ל-
wouldDeleteלפני שמפעילים הוקים אחרים ביעד הגרירה. - תמיד צריך לקרוא ל-
onDragExitעל יעד הגרירה הישן לפני שמפעילים אתonDragEnterעל יעד הגרירה החדש. - צריך להפעיל את
onDragOverאחריonDragEnterבפעם הראשונה שמעבירים את העכבר מעל יעד הגרירה, ובכל קריאה נוספת ל-onDragשבה יעד הגרירה עדיין מופיע מעל העכבר.
onDrag(e, totalDelta) {
// Update the draggable location.
const delta = this.pixelsToWorkspaceUnits(totalDelta);
const newLoc = Coordinate.sum(this.startLoc, delta);
this.draggable.drag(newLoc, e);
// Call wouldDeleteDraggable.
if (isDeletable(this.draggable)) {
this.draggable.setDeleteStyle(
// Checks that the drag target is an `IDeleteArea` and calls `wouldDelete`
// on it.
this.wouldDeleteDraggable(e, this.draggable),
);
}
const newDragTarget = this.workspace.getDragTarget(e);
if (this.dragTarget !== newDragTarget) {
// Call `onDragExit` then `onDragEnter`.
this.dragTarget?.onDragExit(this.draggable);
newDragTarget?.onDragEnter(this.draggable);
}
// Always call `onDragOver`
newDragTarget?.onDragOver(this.draggable);
this.dragTarget = newDragTarget;
}
סיום גרירות
השיטה onEndDrag מסיימת גרירה. הוא צריך להודיע לרכיב הניתן לגרירה שהגרירה הסתיימה, וליעדי גרירה שמוצגים מעל הסמן שהרכיב הניתן לגרירה הופל. הוא צריך גם להיפטר מהרכיב שניתן לגרירה אם יעד הגרירה הוא אזור מחיקה.
- תמיד צריך לקרוא ל-
onDropלפני שיטות אחרות. - צריך להפעיל את
revertDragאם יעד הגרירה מונע גרירה. - צריך להפעיל את
endDragאחרי החזרת הגרירה, אבל לפני השלכת הרכיב. - צריך להפעיל את
disposeאם יעד הגרירה הוא אזור מחיקה.
onDragEnd(e) {
// Call `onDrop` first.
const dragTarget = this.workspace.getDragTarget(e);
if (dragTarget) {
this.dragTarget?.onDrop(this.draggable);
}
// Then revert the drag (if applicable).
if (this.shouldReturnToStart(e, this.draggable)) {
this.draggable.revertDrag();
}
// Then end the drag.
this.draggable.endDrag(e);
// Then delete the draggable (if applicable).
if (
isDeletable(this.draggable) &&
this.wouldDeleteDraggable(e, this.draggable)
) {
this.draggable.dispose();
}
}
הרשמה
צריך לרשום את הכיתה של הגורם שגורר כדי שיהיה אפשר ליצור אותה כשמזוהים גרירות.
// Note that the type is BLOCK_DRAGGER even though draggers drag more than
// blocks. The name is for backwards compatibility.
Blockly.registry.register(registry.Type.BLOCK_DRAGGER, 'MY_DRAGGER', MyDragger);
שימוש
אחרי שמטמיעים את ה-dragger המותאם אישית, אפשר להעביר אותו לאפשרויות ההגדרה כדי להשתמש בו.
const myWorkspace = Blockly.inject('blocklyDiv', {
plugins: {
// Note that we pass this to blockDragger even though draggers drag more
// than blocks. The name is for backwards compatibility.
blockDragger: MyDragger,
},
});