缩放舞台和拖动元素的相对位置不起作用

Scale stage and drag element relative positions not working

我在 KonvaJS React 中计算实时位置时遇到了小问题。在我的示例中,我有两个 Rect 的小(红色)位置是相对于大 Rect(黄色)的,拖动大矩形时,小的相对于大的移动,但是当我向上或向下缩放时小的在x, y位置跳跃了一些像素。

Working example

import React from "react";
import ReactDOM from "react-dom";
import { Rect, Stage, Layer } from "react-konva";

import "./styles.css";

function Box({ attrs, draggable, updateAttr }) {
  const onDragStart = e => {
    const element = e.target;
    if (typeof updateAttr === "function") {
      updateAttr(element._lastPos);
    }
  };

  const onDragMove = e => {
    const element = e.target;
    if (typeof updateAttr === "function") {
      updateAttr(element._lastPos);
    }
  };

  const onDragEnd = e => {
    const element = e.target;
    if (typeof updateAttr === "function") {
      updateAttr(element._lastPos);
    }
  };

  return (
    <Rect
      draggable={draggable}
      onDragEnd={onDragEnd}
      onDragMove={onDragMove}
      onDragStart={onDragStart}
      fill={attrs.fill}
      x={attrs.x}
      y={attrs.y}
      width={attrs.width}
      height={attrs.height}
    />
  );
}

const calculatePos = ({ r1, r2 }) => ({
  ...r2,
  x: parseInt(r1.width + r1.x + 10, 10),
  y: parseInt(r1.y + r1.height / 2 - r2.height / 2, 10)
});

const boxAttr = {
  x: 50,
  y: 50,
  width: 200,
  height: 150,
  fill: "yellow"
};

const secondAttr = calculatePos({
  r2: {
    fill: "red",
    width: 20,
    height: 20
  },
  r1: boxAttr
});

class App extends React.Component {
  state = {
    scale: 1,
    boxAttr,
    secondAttr
  };
  updateScale = scale => {
    this.setState({ scale });
  };

  updateAttr = pos => {
    const { secondAttr, boxAttr } = this.state;
    this.setState({
      secondAttr: calculatePos({
        r2: secondAttr,
        r1: { ...boxAttr, ...pos }
      })
    });
  };

  render() {
    const { scale, boxAttr, secondAttr } = this.state;

    return (
      <div className="App">
        <button
          onClick={() => {
            this.updateScale((parseFloat(scale) + 0.1).toFixed(1));
          }}
        >
          + Scale ({scale})
        </button>

        <button
          onClick={() => {
            this.updateScale((parseFloat(scale) - 0.1).toFixed(1));
          }}
        >
          - Scale ({scale})
        </button>
        <Stage
          scaleX={scale}
          scaleY={scale}
          width={window.innerWidth}
          height={window.innerHeight}
        >
          <Layer>
            <Box
              updateAttr={this.updateAttr}
              draggable={true}
              attrs={boxAttr}
            />
            <Box draggable={false} attrs={secondAttr} />
          </Layer>
        </Stage>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

请帮我更新红色矩形的正确 x,y。


I know Grouped Draggable solution will fix this issue, but I cannot implement in my real application due to complex relations that cannot be group for draggable reason

拖动第一个框时,您必须将 canvas 上的鼠标坐标转换为缩放后 canvas 内的坐标系才能移动第二个框。

我为此修改了 updateAttr 方法。

但是有一个问题,当 konva 本身调用 updateAttr 时(在 dragEnd 事件之后),它会使用转换后的坐标。这就是为什么我向名为 doScale 的 updateAttr 添加了第二个参数。自己调用时,设置为真,它会平移坐标,如果konva调用它,没有第二个参数,它的计算结果为假,不做平移。

代码位于:https://codesandbox.io/s/6126wz0kkk