Не работает масштабная шкала и относительное положение элемента перетаскивания - PullRequest
0 голосов
/ 05 марта 2019

У меня небольшая проблема с вычислением позиции в реальном времени при масштабированном этапе в KonvaJS React.В моем примере у меня две Rect маленькие (красная) одна позиция относительно большой Rect (желтая), хотя при перетаскивании большого прямоугольника маленький перемещается относительно большого, но когда я масштабируюсь вверх или вниз, маленький прыгает на несколькопикселей в x, y позициях.

Рабочий пример

enter image description here

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 для красного прямоугольника.


Я знаю, что решение Grouped Draggable решит эту проблему, но я не могу реализовать его в моем реальном приложении из-за сложных отношений, которые не могут быть сгруппированы по перетаскиваемой причине

1 Ответ

0 голосов
/ 05 марта 2019

При перетаскивании первого поля необходимо переместить координаты мыши на холсте в систему координат внутри масштабированного холста, чтобы переместить второе поле.

Я изменил метод updateAttr, чтобы сделать это.

Однако есть одна загвоздка: когда updateAttr вызывается самой конвой (после события dragEnd), она делает это с переведенными координатами.Вот почему я добавил второй аргумент в updateAttr под названием doScale.Когда вы вызываете его самостоятельно, установите его в true, и он будет переводить координаты, если konva вызывает его, второго аргумента нет, и он оценивается как false и не переводится.

Код доступен по адресу: https://codesandbox.io/s/6126wz0kkk

...