Eliav2 / react-xarrows

Draw arrows (or lines) between components in React!
https://codesandbox.io/embed/github/Eliav2/react-xarrows/tree/master/examples?fontsize=14&hidenavigation=1&theme=dark
MIT License
584 stars 75 forks source link

startBox / endBox props as start / end alternative #68

Closed YuriGor closed 3 years ago

YuriGor commented 3 years ago

I want to render arrows inside the css-scaled (transform:scale(..)) parent.

If scale != 1 - arrows are rendered incorrectly.

Would be great if arrow will have extra optional scale prop (=1 by default) so it will divide all anchors x/y/width/height by this prop value before doing main calculations to compensate applied scaling

I don't use it, (I use native scrolling) but it's also common practice to use transform: translate** to implement pan, or just use transform:matrix to scale/translate at once.

So arrow would have also 'translateX' / 'translateY' props to substract from original values I am not familiar with code, but I don't think it would be a great change, because all calculations will remain same, they will only be based on pre-scaled / pre-translated sizes and positions instead of original values got from html elements.

To make things consistent with css maybe it makes sense to accept scaleX scaleY also separately for reference: https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix()

YuriGor commented 3 years ago

As a workaround applying reversed transform/scale like this:

SVGcanvasStyle={{ transform: `scale(${1 / scale})` }}

seems to fix arrow canvas positions/sizes, but arrows themselves remain of fixed size and do not respect scaling, while the rest of content shrinks/grows.

YuriGor commented 3 years ago

I renamed the feature request. Instead of passing matrix to compensate I suggest to make things simpler and faster: App often already knows the position and size of connected elements, so if arrow would accept this data directly it would solve three problems at once:

Eliav2 commented 3 years ago

Hey friend thank you for the detailed explanations, can you provide code snippets and describe exactly what would you expect

YuriGor commented 3 years ago

Hi @Eliav2 here is a demo for scaling issue + workaround https://codesandbox.io/s/xarrow-scaling-68-ik5gy?file=/src/Board.js so what I suggest, to allow not only passing refs/id like this:

<Xarrow
  start='id1'
  end={ref2}
/>

but also source target geometry directly like this:

<Xarrow
  start={{top:0, left:0,width:100,height:100}}
  end={{top:50, left:50,width:100,height:100}}
/>

In this case arrow will not care about related elements - I will. Instead it will be just rendered as client code needs, in a passive mode.

And these issues with scaling/translation - it will be up to user code to provide these start/end boxes with correct position/size values, xarrow will also not care about scaling/translation - it will do one job but do it well and fast - render cool arrows when and where we need them.

YuriGor commented 3 years ago

I will try to make a PR but I see in contributing notes you are asking to work in dev branch? And dev brunch is nut currently building?

~/Development/react-xarrows$ npm run build

> react-xarrows@1.6.1 build
> tsc -p .

src/index.tsx:707:59 - error TS2554: Expected 0-1 arguments, but got 2.

707   const callOnNextRender = useCallOnNextRender(undefined, useLayoutEffect);
                                                              ~~~~~~~~~~~~~~~

Found 1 error.

Will try in master then.

YuriGor commented 3 years ago

Looks like in my use case it's better to implement my own arrow component rather then change this one.

farukparhat commented 3 years ago

@YuriGor I am facing this same issue, could you share any code you may have on your own arrow component related to this issue or how you got around it? Even with the reverse scaling prop looks like there is significant margin of error in the arrows and I do not want the arrows themselves to increase in stroke size

YuriGor commented 3 years ago

Hi, I implemented my own SVG arrow react component which i render using nodes coordinates stored in db, but not trying to calculate them from source to target on the fly. And i scale parent element with already rendered nodes and arrows inside this way there is no distortion. You can see how its working on planzed.org but I cannot share the code.