맞춤 드래그거

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

드래그 조정에 관해 맞춤설정할 만한 사항이 많지 않으므로 맞춤 드래거를 구현해야 하는 상황은 거의 없습니다. 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에 알리고 마우스 오버된 드래그 타겟에 draggable이 떨어졌음을 알립니다. 또한 드래그 타겟이 삭제 영역인 경우 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,
  },
});