projectstorm / react-diagrams

a super simple, no-nonsense diagramming library written in react that just works
https://projectstorm.cloud/react-diagrams
MIT License
8.51k stars 1.17k forks source link

Changing a node's or size on canvas programmatically #831

Open tabdon opened 3 years ago

tabdon commented 3 years ago

I am trying to create a format bar that can change a node's properties. I'd like to be able to:

1) Drag a node to the canvas 2) Select the node 3) Use the format bars control to change things about the node (size, border, color, etc)

The below code is my attempt to get this working. I am able to change properties (attributes?) on the selected node. However, after doing so, the node doesn't actually change.

(side note: I used Renato's Logossim project as a playground to learn about React Diagrams)

In the NodeWidget code below, I am trying to base the height of the node on the value of the node model. Then, I try to set node model height value from my diagram engine code. I think I'm missing something fundamental about how this is all supposed to work :)

NodeWidget:

export const Shape = ({ size = 90 }, props) => (
  <svg
    height={props.height}
    width={size}
    // omitted
  >
    // omitted
  </svg>
);

const NodeWidget = props => {
  const { model } = props;

  const inputPorts = Object.values(model.getInputPorts());
  const portPositions = distributePorts(inputPorts.length);

  return (
    <Wrapper selected={model.isSelected()}>
      <PortExtension
        selected={model.isSelected()}
        portPositions={portPositions}
      />
      {inputPorts.map((port, i) => (
        <PositionedPort
          key={port.getName()}
          name={port.getName()}
          position={portPositions[i]}
        />
      ))}
      <PositionedPort name="out" />
      <Shape height={model.height} />
    </Wrapper>
  );
};

App.js File:

import components from "./components";
import Diagram from "./Diagram";
import DiagramEngine from "./DiagramEngine";

function App() {
  const [diagram, setDiagram] = useState();

  useEffect(() => {
    const newDiagram = new DiagramEngine(components);
    setDiagram(newDiagram);
  }, []);

  return (
    <>
      {loading ?
        '' :
        <div>
          <button onClick={diagram.changeNodeSize}>
            Click Me
          </button>
          <Diagram engine={diagram}/>
        </div>
      }
  </>
  );
}

App.js File:

class DiagramEngine {
  constructor(components) {
    this.components = components;
    this.initializeEngine();
    this.initializeModel();
  }

  //... code omitted

  changeNodeSize = () => {
    const selectedNodes = this.engine
      .getModel()
      .getSelectedEntities()
      .filter(entity => entity instanceof BaseModel)
      .forEach(node => {
          node.height = 200
       }
      )
    this.engine.repaintCanvas();
  }
}
kobajs commented 3 years ago

You can try node.updateDimensions