Có thể kéo

Có thể kéo là một đối tượng đã kết xuất hình ảnh tồn tại trong không gian làm việc và có thể kéo và thả. Họ triển khai giao diện IDraggable.

Có rất ít trường hợp bạn muốn thêm một đối tượng mới có thể kéo vàoBlockly (ví dụ: trình bổ trợ chọn nhiều lần hoặc thay đổi cách một đối tượng hiện có xử lý các thao tác kéo), vì bạn không thể thêm đối tượng mới kết xuất vào Blockly. Các đối tượng được kết xuất duy nhất có thể tồn tại trong không gian làm việc là các khối, bong bóng trò chuyện và nhận xét trong không gian làm việc.

Yêu cầu của công việc

Thành phần có thể kéo có một số trách nhiệm khi thực thi thao tác kéo:

  • Di chuyển các phần tử svg sang lớp kéo.
  • Dịch các phần tử svg.
  • Kích hoạt sự kiện di chuyển.

Triển khai

Để tạo một thành phần có thể kéo mới, bạn phải triển khai giao diện IRenderedElementIDraggable. Điều này cho phép Blockly biết rằng đối tượng của bạn đang hiển thị và có thể được kéo.

class MyDraggable extends IRenderedElement, IDraggable {}

Trả về phần tử SVG gốc

Phương thức getRootSvg trả về phần tử svg gốc (thường là một nhóm) chứa mọi phần tử khác tạo nên khung hiển thị cho đối tượng có thể kéo được.

getSvgRoot() {
  return this.rootSvg;
}

Khả năng di chuyển của lượt trả về

Phương thức isMovable sẽ trả về xem hiện có thể di chuyển đối tượng có thể kéo hay không (vì bạn có thể tạm thời tắt tính năng kéo một đối tượng). Nếu isMovable trả về false, thì không gian làm việc sẽ được kéo.

isMovable() {
  return true;
}

Vị trí trả hàng

Phương thức getRelativeToSurfaceXY trả về một Coordinate chỉ định vị trí góc bắt đầu trên cùng của đối tượng có thể kéo trong toạ độ không gian làm việc.

Toạ độ không gian làm việc có gốc ở góc bên trái tuyệt đối và phía trên cùng tuyệt đối của không gian làm việc. Đồng thời, chúng sẽ không thay đổi khi không gian làm việc được điều chỉnh theo tỷ lệ hoặc di chuyển.

getRelativeToSurfaceXY() {
  return this.loc;
}

Bắt đầu kéo

Phương thức startDrag khởi chạy thao tác kéo vào đối tượng có thể kéo. Phương thức này không di chuyển phần có thể kéo. Tuy nhiên, bạn nên lưu trữ mọi dữ liệu hoặc tạo bất kỳ đối tượng nào cần thiết để hoàn thành quá trình kéo. Điều này bao gồm mọi dữ liệu cần thiết để đảo ngược lệnh kéo nếu revertDrag được gọi.

Bạn cũng nên thay đổi các phần tử svg để nằm trên lớp kéo của không gian làm việc, để chúng tồn tại phía trên mọi thành phần khác.

Tính năng này cũng tham gia một sự kiện mà bạn có thể dùng để kiểm tra xem có phím đã nhấn hay không. Điều này cho phép (chẳng hạn như) bạn xử lý thao tác kéo trong khi dịch chuyển khác với thao tác kéo thông thường.

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

Phương trình lực cản

Phương thức drag thực sự di chuyển đối tượng có thể kéo. newLoc nằm trong toạ độ không gian làm việc và cũng có một sự kiện được truyền qua mà bạn có thể sử dụng để kiểm tra các phím đã nhấn.

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

Huỷ bỏ các thao tác kéo

Phương thức revertDrag trả về vị trí có thể kéo khi bắt đầu kéo. Chẳng hạn, hiện tượng này xảy ra nếu mục có thể kéo được thả vào mục tiêu kéo đang ngăn cản chuyển động.

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

Kết thúc kéo

Phương thức endDrag dọn dẹp thao tác kéo, giải phóng mọi dữ liệu hoặc đối tượng đã lưu trữ và đưa đối tượng có thể kéo về lớp ban đầu.

endDrag luôn được gọi sau revertDrag nếu revertDrag được gọi.

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

Lựa chọn

Phần tử được kéo được xác định theo phần tử được chọn khi phát hiện thao tác kéo.

ISelectable

Để được chọn, thành phần có thể kéo phải triển khai giao diện 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.
  }
}

Đặt lựa chọn

Bạn có thể đặt phần tử đã chọn bằng cách gọi Blockly.common.setSelected(). thường, bạn cần thực hiện việc này để phản hồi sự kiện pointerdown của người dùng.

  constructor() {
    this.initSvg();

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

Khả năng tương thích

Thành phần kéo được của bạn có thể triển khai các giao diện bổ sung để có thể tương tác với các hệ thống khác trong Blockly.

Có thể xóa

Bạn có thể triển khai giao diện IDeleteable để cho phép thao tác kéo có thể được xử lý bằng thùng rác hoặc các mục tiêu xoá khác.

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

Có thể sao chép

Bạn có thể triển khai giao diện ICopyable để cho phép sao chép nội dung có thể kéo và xác định IPaster để cho phép dán nội dung đó.

Để biết thêm thông tin về cách sao chép và dán, hãy xem bài viết Sao chép và dán.