Coder Social home page Coder Social logo

Rotatable parent node about xyflow HOT 5 OPEN

MatheusRoichman avatar MatheusRoichman commented on September 21, 2024
Rotatable parent node

from xyflow.

Comments (5)

moklick avatar moklick commented on September 21, 2024

Hey @MatheusRoichman

rotation is not built in and if you rotate a parent, the coordinate system stays the same and you would have to do some maths, to position the child nodes correctly.

from xyflow.

MatheusRoichman avatar MatheusRoichman commented on September 21, 2024

What is the calculus that I need to do with the child nodes to position them correctly? I tried some, but I'm still not able to do it,

from xyflow.

hocman2 avatar hocman2 commented on September 21, 2024

What is the calculus that I need to do with the child nodes to position them correctly? I tried some, but I'm still not able to do it,

Have you tried rotating your node around the center of it's parent ?

You would use the formula
x' = x * cos(angle) - y * sin(angle)
y' = x * sin(angle) + y * cos(angle)

Applied to your case that would be:
Because the parent node is 400x400, we can think of the relative position of your child node as x:-200; y:200 from the center (Y points UP)

The angle would be 90° or PI/2 radians

The new relative position would be
x' = -200 * cos(PI/2) - 200 * sin(PI/2) = -200
y' = -200 * sin(PI/2) + 200 * cos(PI/2) = -200

You can then use this new relative position to place down your child node. IDK how your positioning system works in detail so i'll leave it here.

You will also need to rotate your child node in-place (as you are already doing) by the same angle

from xyflow.

MatheusRoichman avatar MatheusRoichman commented on September 21, 2024

What is the calculus that I need to do with the child nodes to position them correctly? I tried some, but I'm still not able to do it,

Have you tried rotating your node around the center of it's parent ?

You would use the formula x' = x * cos(angle) - y * sin(angle) y' = x * sin(angle) + y * cos(angle)

Applied to your case that would be: Because the parent node is 400x400, we can think of the relative position of your child node as x:-200; y:200 from the center (Y points UP)

The angle would be 90° or PI/2 radians

The new relative position would be x' = -200 * cos(PI/2) - 200 * sin(PI/2) = -200 y' = -200 * sin(PI/2) + 200 * cos(PI/2) = -200

You can then use this new relative position to place down your child node. IDK how your positioning system works in detail so i'll leave it here.

You will also need to rotate your child node in-place (as you are already doing) by the same angle

I tried it. Here's my implementation of this formula;

export const rotateNodeAroundParentCenter = (
  node: Node,
  angle: number,
  parentCenter: XYPosition
): XYPosition => {
  const x = parentCenter.x - node.position.x;
  const y = parentCenter.y - node.position.y;

  const angleCos = Math.cos(angle);
  const angleSin = Math.sin(angle);

  const newX = x * angleCos - y * angleSin;
  const newY = x * angleSin + y * angleCos;

  return {
    x: newX,
    y: newY,
  };
};

export const getNodeCenter = (node: Node): XYPosition => {
  const rect = getNodesBounds([node]);

  return {
    x: rect.width / 2,
    y: rect.height / 2,
  };
};
const handleRotate = useCallback(
  (e: DragEvent) => {
    if (!rotateControlRef.current || !resizerRef.current) return;

    e.dataTransfer.effectAllowed = "none";

    const rect = rotateControlRef.current.getBoundingClientRect();
    const centerX = rect.left + rect.width / 2;
    const centerY = rect.top + rect.height / 2;
    const dx = e.clientX - centerX;
    const dy = e.clientY - centerY;
    const rad = Math.atan2(dy, dx);
    const deg = (rad * 180) / Math.PI;

    const roundedDeg = parseInt(deg.toString());
    if (roundedDeg === roundedRotation) return;

    setNodes((nds) =>
      nds.map((node) => {
        if (
          !nodeOfThisElement ||
          (node.id !== element.id && node.parentNode !== element.id)
        )
          return node;

        const updatedNode = node as DesignElementNodeType;
        updatedNode.data.rotation = roundedDeg;

        if (updatedNode.parentNode === element.id) {
          const parentCenter = getNodeCenter(nodeOfThisElement);

          const childPosition = rotateNodeAroundParentCenter(
            updatedNode,
            roundedDeg,
            parentCenter
          );

          updatedNode.position = childPosition;
        }

        return updatedNode;
      })
    );

    setRotation(roundedDeg);
    updateNodeInternals(nodeId);
  },
  [
    element.id,
    nodeId,
    nodeOfThisElement,
    roundedRotation,
    setNodes,
    updateNodeInternals,
  ]
);

Didn't worked well.

2024-03-08.11-37-47.online-video-cutter.com.mp4

from xyflow.

hocman2 avatar hocman2 commented on September 21, 2024

Your angle needs to be in radians and beware that the getNodeCenter() function does not return the global canvas center. For that it'd need to return x + width / 2 and y + height / 2. IDK If it's what you want though

Then I'd recommend logging x and y coordinates at different steps of the rotateAround function to see if the results are what you expect for offsetting the child. Depending on how coordinates work the implementations may differ so a simple stackoverflow copy paste might not be enough

from xyflow.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.