드래거

드래거는 사용자 상호작용에 응답하여 드래그 가능한 항목의 드래그를 조정하는 컨트롤러 객체입니다.

드래그 조정에 관해 맞춤설정할 만한 사항이 많지 않으므로 맞춤 드래거를 구현해야 하는 경우는 거의 없습니다. scroll-options 플러그인은 작업공간 가장자리에 스크롤을 추가하여 픽셀 좌표가 작업공간 좌표로 변환되는 방식을 변경하기 위해 맞춤 드래거를 구현합니다.

책임

드래거는 드래그를 실행할 때 다음과 같은 몇 가지 책임이 있습니다.

  • draggable에서 drag 메서드를 호출합니다.
  • 드래그 가능한 요소가 이동해야 하는 위치를 워크스페이스 좌표로 계산합니다.
  • 마우스 오버된 드래그 타겟에서 드래그 타겟 메서드를 호출합니다.

구현

맞춤 드래거를 만들려면 IDragger 인터페이스를 구현해야 합니다.

class MyDragger implements IDragger {
  // Takes in the draggable being dragged and the workspace the drag
  // is occurring in.
  constructor(draggable, workspace);
}

이미 기본 책임을 처리하는 기본 제공 Blockly.dragging.Dragger를 서브클래스화할 수도 있습니다.

드래그 시작

onDragStart 메서드는 드래그를 초기화합니다. 드래그를 실행하는 데 필요한 모든 데이터를 저장해야 합니다. 또한 드래그되는 드래그 가능한 요소에서 startDrag를 호출해야 합니다.

onDragStart(e) {
  this.startLoc = this.draggable.getRelativeToSurfaceXY();

  this.draggable.startDrag(e);
}

드래그

onDrag 메서드는 드래그를 실행합니다. 드래그 가능한 요소의 새 작업공간 위치를 계산해야 합니다. 이 위치는 픽셀 좌표로 지정된 totalDelta를 기반으로 계산됩니다.

또한 마우스를 가져간 드래그 타겟도 업데이트해야 합니다.

  • wouldDelete는 드래그 타겟에서 다른 후크를 호출하기 전에 항상 호출해야 합니다.
  • 새 드래그 타겟에서 onDragEnter를 호출하기 전에 항상 이전 드래그 타겟에서 onDragExit를 호출해야 합니다.
  • onDragOver는 드래그 타겟이 처음으로 마우스 오버될 때 onDragEnter 후에 호출되어야 하며, 드래그 타겟이 여전히 마우스 오버된 상태인 onDrag의 추가 호출마다 호출되어야 합니다.
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;
}

드래그 종료

onEndDrag 메서드는 드래그를 종료합니다. 드래그 가능 항목에 드래그가 종료되었음을 알리고 마우스 오버된 드래그 타겟에 해당 드래그 가능 항목이 드롭되었음을 알려야 합니다. 또한 드래그 타겟이 삭제 영역인 경우 draggable을 폐기해야 합니다.

  • onDrop는 항상 다른 메서드보다 먼저 호출해야 합니다.
  • 드래그 타겟이 드래그를 차단하는 경우 revertDrag를 호출해야 합니다.
  • endDrag는 드래그를 되돌린 후, 그러나 삭제하기 전에 호출해야 합니다.
  • 드래그 타겟이 삭제 영역인 경우 dispose를 호출해야 합니다.
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();
  }
}

등록

드래그가 감지될 때 생성될 수 있도록 드래거 클래스를 등록해야 합니다.

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

사용

맞춤 드래거를 구현한 후에는 이를 주입 구성 구조체에 전달하여 사용할 수 있습니다.

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