גורר הוא אובייקט של בקר שמרכז את משיכת רכיבים שניתן לגרור בתגובה לאינטראקציות של משתמשים.
יש מעט מאוד מצבים שבהם כדאי להטמיע רכיב גרירה בהתאמה אישית, כי אין הרבה דברים שתרצו להתאים אישית בנוגע לתיאום של גרירה. התוסף 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,
},
});