Elementos arrastrables personalizados

Un elemento arrastrable es un objeto renderizado que existe en el espacio de trabajo y se puede arrastrar y soltar. Implementan la interfaz IDraggable.

Hay muy pocas circunstancias en las que querrías agregar un nuevo elemento arrastrable a Blockly (p.ej., el complemento multiselect o cambiar la forma en que un objeto existente controla los arrastres), ya que no puedes agregar nuevos objetos renderizados a Blockly. Los únicos objetos renderizados que pueden existir dentro de un espacio de trabajo son los bloques, las burbujas y los comentarios del espacio de trabajo.

Responsabilidades

Los elementos arrastrables tienen varias responsabilidades cuando se ejecutan arrastres:

Implementación

Para crear un elemento arrastrable nuevo, debes implementar las interfaces IRenderedElement y IDraggable. Esto le permite a Blockly saber que tu objeto es visible y se puede arrastrar.

class MyDraggable extends IRenderedElement, IDraggable {}

Devuelve el elemento SVG raíz.

El método getRootSvg devuelve el elemento SVG raíz (por lo general, un grupo) que contiene todos los demás elementos que componen la vista del elemento arrastrable.

getSvgRoot() {
  return this.rootSvg;
}

Capacidad de devolución

El método isMovable devuelve si el elemento arrastrable se puede mover en este momento (ya que es posible que desees inhabilitar temporalmente el arrastre de un objeto). Si isMovable devuelve false, se arrastra el espacio de trabajo.

isMovable() {
  return true;
}

Posición de devolución

El método getRelativeToSurfaceXY devuelve un Coordinate que especifica la ubicación de la esquina superior izquierda del elemento arrastrable en las coordenadas del espacio de trabajo.

Las coordenadas del espacio de trabajo tienen un origen en la parte superior izquierda absoluta del espacio de trabajo. Además, no cambian cuando se ajusta o mueve el espacio de trabajo.

getRelativeToSurfaceXY() {
  return this.loc;
}

Cómo iniciar arrastres

El método startDrag inicializa un arrastre en el elemento arrastrable. Este método no mueve el elemento arrastrable. Sin embargo, debes almacenar los datos o construir los objetos que necesites para completar la acción de arrastrar. Esto incluye cualquier dato que necesites para revertir la acción de arrastrar si se llama a revertDrag.

También debería cambiar los elementos SVG para que estén en la capa de arrastre del espacio de trabajo, de modo que existan por encima de cualquier otro elemento.

También toma un evento, que puedes usar para verificar las teclas presionadas. Esto te permite (por ejemplo) tratar un arrastre mientras cambias de marcha de manera diferente a un arrastre 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...
}

Arrastra

El método drag mueve el objeto arrastrable. El newLoc se encuentra en coordenadas del espacio de trabajo, y también se pasa un evento que puedes usar para verificar las teclas presionadas.

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

Cómo revertir arrastres

El método revertDrag devuelve el elemento arrastrable a la posición en la que se encontraba al comienzo del arrastre. Esto sucede, por ejemplo, si el elemento arrastrable se suelta en un destino de arrastre que impide el movimiento.

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

Finalizar arrastres

El método endDrag limpia un arrastre, libera los datos o los objetos almacenados y devuelve el elemento arrastrable a su capa original.

Siempre se llama a endDrag después de revertDrag si se llama a revertDrag.

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);
}

Selección

El elemento que se arrastra se determina según el elemento que está seleccionado cuando se detecta un arrastre.

ISelectable

Para que se pueda seleccionar un elemento arrastrable, este debe implementar la interfaz 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.
  }
}

Establecer selección

El elemento seleccionado se puede configurar llamando a Blockly.common.setSelected(). Por lo general, querrás hacerlo en respuesta a un evento pointerdown del usuario.

  constructor() {
    this.initSvg();

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

Compatibilidad

El elemento arrastrable puede implementar interfaces adicionales para que pueda interactuar con otros sistemas en Blockly.

Se puede borrar

Puedes implementar la interfaz IDeleteable para permitir que la papelera o cualquier otro destino de eliminación desechen el elemento arrastrable.

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.
  }
}

Se puede copiar

Puedes implementar la interfaz ICopyable para permitir que se copie tu elemento arrastrable y definir un IPaster para permitir que se pegue.

Para obtener más información sobre cómo copiar y pegar, consulta Copiar y pegar.