Elemento que pode ser arrastado personalizado

Um elemento arrastável é um objeto renderizado que existe no espaço de trabalho e pode ser arrastado e solto. Elas implementam a interface IDraggable.

Há pouquíssimas circunstâncias em que você precisaria adicionar um novo elemento arrastável ao Blockly (por exemplo, o plug-in de multisseleção ou mudar a forma como um objeto atual processa arrastos), porque não é possível adicionar novos objetos renderizados ao Blockly. Os únicos objetos renderizados que podem existir em um espaço de trabalho são blocos, balões e comentários do espaço de trabalho.

Responsabilidades

Os elementos arrastáveis têm várias responsabilidades ao executar arrastos:

Implementação

Para criar um novo elemento arrastável, é preciso implementar as interfaces IRenderedElement e IDraggable. Isso informa ao Blockly que seu objeto está visível e pode ser arrastado.

class MyDraggable extends IRenderedElement, IDraggable {}

Retornar o elemento SVG raiz

O método getRootSvg retorna o elemento svg raiz (geralmente um grupo) que contém todos os outros elementos que compõem a visualização do elemento arrastável.

getSvgRoot() {
  return this.rootSvg;
}

Retornar capacidade de movimentação

O método isMovable retorna se o elemento arrastável pode ser movido no momento (já que talvez você queira desativar temporariamente o arrastar de um objeto). Se isMovable retornar false, o espaço de trabalho será arrastado.

isMovable() {
  return true;
}

Posição de retorno

O método getRelativeToSurfaceXY retorna um Coordinate que especifica a localização do canto superior esquerdo do elemento arrastável nas coordenadas do espaço de trabalho.

As coordenadas do espaço de trabalho têm uma origem na parte superior e esquerda absolutas do espaço de trabalho. Eles não mudam quando o espaço de trabalho é dimensionado ou movido.

getRelativeToSurfaceXY() {
  return this.loc;
}

Iniciar ações de arrastar

O método startDrag inicializa uma ação de arrastar no elemento arrastável. Esse método não move o elemento arrastável. Mas você precisa armazenar os dados ou construir os objetos necessários para concluir a ação de arrastar. Isso inclui todos os dados necessários para reverter a ação de arrastar se revertDrag for chamado.

Ele também precisa mudar os elementos SVG para a camada de arrastar do espaço de trabalho, para que fiquem acima de qualquer outro elemento.

Ele também recebe um evento, que pode ser usado para verificar se há teclas pressionadas. Isso permite, por exemplo, tratar uma ação de arrastar enquanto pressiona a tecla Shift de maneira diferente de uma ação de arrastar normal.

startDrag(e) {
  // Save the original location so we can revert the drag.
  this.startLoc = this.getRelativeToSurfaceXY();

  // Disable resizing the workspace for performance.
  this.workspace.setResizesEnabled(false);

  // Put the element on the drag layer.
  this.workspace.getLayerManager()?.moveToDragLayer(this);

  // Fire a drag event...

  // etc...
}

Arrastar

O método drag move o objeto arrastável. O newLoc está nas coordenadas do espaço de trabalho, e também há um evento transmitido que pode ser usado para verificar as teclas pressionadas.

drag(newLoc, e) {
  this.moveTo(newLoc);
}

Reverter ações de arrastar

O método revertDrag retorna o elemento arrastável à posição em que estava no início da ação de arrastar. Isso acontece se, por exemplo, o elemento arrastável for solto em um destino de arrasto que impede o movimento.

revertDrag() {
  // Move back to the position that was stored in `startDrag`.
  this.moveTo(this.startLoc);
}

Finalizar ações de arrastar

O método endDrag limpa uma ação de arrastar, liberando dados ou objetos armazenados e retornando o elemento arrastável à camada original.

endDrag sempre é chamado depois de revertDrag, se revertDrag for chamado.

endDrag() {
  // Put the element back on its original layer (in this case BLOCK).
  this.workspace
    .getLayerManager()
    ?.moveOffDragLayer(this, Blockly.layers.BLOCK);

  // Allow the workspace to start resizing again.
  this.workspace.setResizesEnabled(true);
}

Seleção

O elemento arrastado é determinado pelo elemento selecionado quando um arrasto é detectado.

ISelectable

Para ser selecionado, um elemento arrastável precisa implementar a interface ISelectable.

class MyDraggable implements ISelectable {
  constructor(workspace) {
    this.id = Blockly.utils.idGenerator.genUid();
    this.workspace = workspace;
  }

  select() {
    // Visually indicate this draggable is selected.
  }

  unselect() {
    // Visually indicate this draggable is not selected.
  }
}

Definir seleção

O elemento selecionado pode ser definido chamando Blockly.common.setSelected(). Normalmente, isso é feito em resposta a um evento pointerdown do usuário.

  constructor() {
    this.initSvg();

    Blockly.browserEvents.conditionalBind(
      this.getSvgRoot(),
      'pointerdown',
      this,
      () => Blockly.common.setSelected(this));
  }

Compatibilidade

O elemento arrastável pode implementar outras interfaces para interagir com outros sistemas no Blockly.

Excluíveis

Você pode implementar a interface IDeleteable para permitir que seu elemento arrastável seja descartado pela lixeira ou outros destinos de exclusão.

class MyDraggable implements IDeletable {
  isDeletable() {
    return true;
  }

  dispose() {
    // Dispose of any references to data or SVG elements.
  }

  setDeleteStyle() {
    // Visually indicate that the draggable is about to be deleted.
  }
}

Copiável

Você pode implementar a interface ICopyable para permitir que o elemento arrastável seja copiado e definir um IPaster para permitir que ele seja colado.

Para mais informações sobre copiar e colar, consulte Copiar e colar.