Un elemento di trascinamento è un oggetto controller che coordina il trascinamento dei elementi trascinabili in risposta alle interazioni degli utenti.
Esistono pochissime circostanze in cui è consigliabile implementare un cursore personalizzato, perché non ci sono molti aspetti che è possibile personalizzare per quanto riguarda il coordinamento di uno scorrimento. Il plug-in scroll-options implementa un cursore personalizzato perché voleva aggiungere lo scorrimento all'estremità dell'area di lavoro, il che cambia il modo in cui le coordinate dei pixel vengono convertite in coordinate dell'area di lavoro.
Responsabilità
Il trascinatore ha diverse responsabilità durante l'esecuzione dei trascinamenti:
- Chiamata dei metodi di trascinamento sull'elemento trascinabile.
- Calcolo della posizione in cui deve spostarsi l'elemento trascinabile nelle coordinate dell'area di lavoro.
- Chiamata a metodi di trascinamento su qualsiasi target di trascinamento al passaggio del mouse.
Implementazione
Per creare un cursore personalizzato, devi implementare l'interfaccia IDragger
.
class MyDragger implements IDragger {
// Takes in the draggable being dragged and the workspace the drag
// is occurring in.
constructor(draggable, workspace);
}
Puoi anche creare una sottoclasse di Blockly.dragging.Dragger
integrato, che gestisce già le responsabilità di base.
Inizia i trascinamenti
Il metodo onDragStart
inizializza un trascinamento. Deve memorizzare tutti i dati necessari per eseguire il trascinamento. Dovrebbe anche chiamare startDrag
sull'elemento draggable in fase di trascinamento.
onDragStart(e) {
this.startLoc = this.draggable.getRelativeToSurfaceXY();
this.draggable.startDrag(e);
}
Resistenza aerodinamica
Il metodo onDrag
esegue un trascinamento. Dovrebbe calcolare la nuova posizione dell'area di lavoro per l'elemento spostabile in base a totalDelta
, che viene fornito in coordinate in pixel.
Dovrebbe anche aggiornare tutti i target di trascinamento su cui viene eseguito il passaggio del mouse.
wouldDelete
deve essere sempre chiamato prima di chiamare altri hook sul target di trascinamento.onDragExit
deve sempre essere chiamato sul vecchio target di trascinamento prima di chiamareonDragEnter
sul nuovo target di trascinamento.onDragOver
deve essere chiamato dopoonDragEnter
la prima volta che il target di trascinamento viene visualizzato e a ogni chiamata aggiuntiva aonDrag
in cui il target di trascinamento è ancora visualizzato.
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;
}
Interrompi i trascinamenti
Il metodo onEndDrag
termina un trascinamento. L'elemento trascinabile dovrebbe comunicare che il trascinamento
è terminato e all'eventuale oggetto di trascinamento su cui è stato passato il mouse che è stato rilasciato. Deve anche eliminare l'elemento spostabile se il target di trascinamento è un'area di eliminazione.
onDrop
deve sempre essere chiamato prima degli altri metodi.revertDrag
deve essere chiamato se il target di trascinamento impedisce i trascinamenti.endDrag
deve essere chiamato dopo l'annullamento del trascinamento, ma prima dell'eliminazione.dispose
deve essere chiamato se il target di trascinamento è un'area di eliminazione.
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();
}
}
Registrazione
La classe dragger deve essere registrata in modo che possa essere creata al rilevamento dei trascinamenti.
// 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);
Utilizzo
Dopo aver implementato il cursore personalizzato, puoi utilizzarlo passandolo alla struttura di configurazione dell'iniezione.
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,
},
});