如何使用 JavaScript 中应用的缩放比例平移来计算拖动时元素的正确位置

问题描述 投票:0回答:1

我正在开发以下拖放库作为一个副项目。我正在使用变换翻译来使元素可拖动。我存储初始的 client.x 和 client.y,并通过鼠标移动时减去当前的 client.x 和 client.y 来计算翻译值。简单来说,我记录初始单击坐标(x,y),当我减去鼠标移动时的当前坐标(x,y)时,它将给出鼠标从初始位置移动的距离,然后将其应用于使用翻译的元素。

它按预期工作。我什至实现了光标偏移,它也可以工作,但我唯一无法弄清楚的是,如果将缩放属性应用于元素,如何调整位置。当元素比例从 1 更改为任何其他值时,元素的大小和位置都会发生变化,这会扰乱我当前的计算。

我创建了一个简单的图表,您可以在这里看到。我还分享了下面的屏幕截图。

diagram for drag and drop element

您可能需要了解程序的流程,所以下面是一个简单的解释

  • 当元素可拖动时,指针向下事件会附加到触发器dragStart。
  • dragStart 创建默认拖动预览,设置初始位置和光标偏移量
  • 拖动元素时,调用#translateDragPreview方法来设置元素的位置。

元素的位置由以下两个方法处理

  #translateDragPreview(x?: number, y?: number) {
    if (this.#draggedPreview.element === null) return;
    const cords = {
      x: x ?? this.#internalState.activeCords.x,
      y: y ?? this.#internalState.activeCords.y,
    };

    const initialX = this.#initialPosition.x / this.#draggedPreview.scale;
    const initialY = this.#initialPosition.y / this.#draggedPreview.scale;

    this.#draggedPreview.element.style.transform = `translate(
    ${cords.x - initialX}px, 
    ${cords.y - initialY}px) 
    scale(${this.#draggedPreview.scale})`;
  }
  #setCursorOffset(
    dragElement: HTMLElement,
    event: PointerEvent,
    offset: BaseDraggableType["modifiers"]["cursor"]["offset"],
  ) {
    const cursorOffset = offset;
    const rect = dragElement.getBoundingClientRect();
    const { scale } = this.#draggedPreview;

    const clickX = this.#internalState.initialCords.x - rect.left;
    const clickY = this.#internalState.initialCords.y - rect.top;

    const adjustRect: (value: number) => number = (value) => value + (value - value / scale);
    const adjustedRect = {
      left: rect.left / scale,
      right: adjustRect(rect.right),
      top: adjustRect(rect.top),
      bottom: adjustRect(rect.bottom),
      width: adjustRect(rect.width),
      height: adjustRect(rect.height),
    };

    const presetOffset = {
      "top-left": {
        x: adjustedRect.left - cursorOffset.x,
        y: adjustedRect.top - cursorOffset.y,
      },
      "top-right": {
        x: adjustedRect.right + cursorOffset.x,
        y: adjustedRect.top - cursorOffset.y,
      },
      "bottom-left": {
        x: adjustedRect.left - cursorOffset.x,
        y: adjustedRect.bottom + cursorOffset.y,
      },
      "bottom-right": {
        x: adjustedRect.right + cursorOffset.x,
        y: adjustedRect.bottom + cursorOffset.y,
      },
      center: {
        x: adjustedRect.left + adjustedRect.width / 2 + cursorOffset.x - 4,
        y: adjustedRect.top + adjustedRect.height / 2 + cursorOffset.y - 2,
      },
      auto: {
        x: adjustedRect.left + clickX + cursorOffset.x,
        y: adjustedRect.top + clickY + cursorOffset.y,
      },
    };

    this.#initialPosition = presetOffset[cursorOffset.preset];
  }

更多信息

  • this.#internalState.activeCords 存储当前的client.x和client.y
  • this.#internalState.initialCords.x 存储初始点击坐标(x,y)
  • this.#initialPosition 存储应用了偏移量的 intialPosition。我也尝试调整比例,但如果比例值大于或小于 1,则不起作用

这里是一个带有设置的代码沙箱链接。请检查index.html和main.ts文件。在 main.ts 文件中,您可以看到 DragOptions 的缩放选项设置为 1,如果您将其更改为任何其他值,则元素位置将无法正确设置。 您还可以将预设更改为以下任意一项

  • 预设:“左上角”| “右上角”| “左下角”| “右下角” | “中心”| “自动”;

如果您不想查看所有代码,您可以帮助我制定如何计算使用平移拖动元素并调整比例值时的正确位置。应用比例时,大小和位置会发生变化以及如何调整,我需要一个公式。

我还在codepen中创建了一个简单的演示。请看一下。这与我在图书馆中使用的方法相同。

如果需要任何进一步的信息,请告诉我,我很乐意提供帮助。

javascript html css drag-and-drop drag
1个回答
0
投票

由于没有得到任何回复,我尝试自己解决。我还找到了一个工作解决方案,我已将其添加到 codepen 链接中。

这是工作解决方案的链接 - https://codepen.io/gokunik/pen/YzmqQJV

下面是一个小片段

function onPointerDown(e, element) {
  const originalRect = element.getBoundingClientRect();
  const rect = scaleRect(element.getBoundingClientRect(), scale);

  initialCoords = {
    x:
      e.clientX +
      (rect.right - e.clientX) +
      (e.clientX - originalRect.right) * scale,
    y:
      e.clientY +
      (rect.bottom - e.clientY) +
      (e.clientY - originalRect.bottom) * scale,
  };
  draggedPreview = element;
  translateDragPreview(e.clientX, e.clientY);
}

解决问题所采用的方法。

我使用了一个简单的方法。我最初在解决这个问题时想到了这个,但当时没有继续下去,但当我现在尝试时它起作用了。

因此,我们的想法是,元素在被拖动时会按比例缩小,因此它的大小会缩小或增加,从而更改其矩形值,例如 x、y、顶部、左侧等,从而取代需要调整的拖动元素。因此,首先我添加了一个函数,以便在应用缩放时为元素提供更新的矩形。现在我有了原始和拖动缩放元素的矩形。

如果您在我共享的屏幕截图中注意到,缩放后的元素通过保持其与原始元素的中心来缩小和增加尺寸,因此首先我尝试使用

(rect.right - e.clientX)
(rect.bottom - e.clientY) 将缩放后的元素边缘与初始单击点对齐
刚刚将元素与右下角对齐。

现在我所要做的就是找到原始矩形中发生点击的位置,并将其缩小以获得更新的缩放矩形。所以我重复了同样的事情,并将其与缩放值

(e.clientX - originalRect.right) * scale
(e.clientY - originalRect.bottom) * scale
相乘,以便根据缩放的元素进行调整。

我希望您觉得这有帮助。我在互联网上没有找到这个问题的答案,这就是我在这里分享的原因。

© www.soinside.com 2019 - 2024. All rights reserved.