Arrastar

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 chamar onDragEnter no novo alvo de arrasto.
  • O onDragOver precisa ser chamado após onDragEnter na primeira vez que o alvo de arrasto é destacado e em cada chamada adicional para onDrag 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,
  },
});