Um arrastador é um objeto de controle que coordena o arrasto de elementos arrastáveis em resposta às interações do usuário.
Existem poucas circunstâncias em que é recomendado implementar um arrastador personalizado, porque não há muito que você queira personalizar sobre como coordenar uma ação de arrastar. O plug-in de opções de rolagem implementa um arrastar personalizado porque quer adicionar rolagem à borda do espaço de trabalho, o que muda a forma como as coordenadas de pixel são convertidas em coordenadas do espaço de trabalho.
Responsabilidades
Ele tem várias responsabilidades ao executar ações de arrastar:
- Chamar métodos de arrasto no elemento arrastável.
- Cálculo da posição para a qual o elemento arrastável precisa se mover nas coordenadas do espaço de trabalho.
- Chamar métodos de destino de arrasto em qualquer destino de arrasto com o cursor.
Implementação
Para criar uma barra de arrastar personalizada, você precisa implementar a interface
IDragger
.
class MyDragger implements IDragger {
// Takes in the draggable being dragged and the workspace the drag
// is occurring in.
constructor(draggable, workspace);
}
Também é possível criar uma subclasse do Blockly.dragging.Dragger
integrado, que já lida com as
responsabilidades básicas.
Iniciar arraste
O método onDragStart
inicializa uma ação de arrastar. Ele precisa armazenar todos os dados necessários para
executar o arrasto. Ele também precisa chamar startDrag
no elemento arrastável
que está sendo arrastado.
onDragStart(e) {
this.startLoc = this.draggable.getRelativeToSurfaceXY();
this.draggable.startDrag(e);
}
Arrasto
O método onDrag
executa um arrasto. A nova posição do espaço de trabalho
para o elemento arrastável precisa ser calculada com base no totalDelta
, que é fornecido nas coordenadas
de pixel.
Ele também precisa atualizar todos os destinos de arrasto que estão sendo apontados.
- O
wouldDelete
sempre precisa ser chamado antes de outros ganchos no destino de arrasto. - O
onDragExit
sempre precisa ser chamado no alvo de arrasto antigo antes de chamaronDragEnter
no novo alvo de arrasto. - O
onDragOver
precisa ser chamado apósonDragEnter
na primeira vez que o alvo de arrasto é destacado e em cada chamada adicional paraonDrag
em que o alvo de arrasto ainda está destacado.
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;
}
Parar de arrastar
O método onEndDrag
encerra uma ação de arrastar. Ele precisa notificar o elemento arrastável de que o arrastamento
terminou e que o elemento foi descartado em qualquer destino de arrastamento que esteja sobre o cursor. Ele
também precisa descartar o elemento arrastável se o destino de arrasto for uma área de exclusão.
- O método
onDrop
sempre precisa ser chamado antes de outros métodos. revertDrag
precisa ser chamado se o destino de arrasto impedir o arrasto.- O método
endDrag
precisa ser chamado após reverter o arrasto, mas antes de descartar. dispose
precisa ser chamado se o destino de arrasto for uma área de exclusão.
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();
}
}
Registro
Sua classe de arrasto precisa ser registrada para que possa ser criada quando os arrastamentos forem detectados.
// 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);
Uso
Depois de implementar o arrastador personalizado, é possível usá-lo transmitindo-o para a estrutura de configuração de injeção.
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,
},
});