question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Arrows from a box back to itself don't look so good

See original GitHub issue

Definitely for state machines and potentially for other use cases as well it’d be awesome to have support for arrows that go from a box back to itself. This would represent a transition from one state to the same state in a state machine-y world which is super valid if you ask me. Here’s what happens now:

Screen Shot 2020-09-18 at 8 41 09 AM

I would be happy to work on (or get someone to work on) this but I think it’d be cool to agree on what the perfect version of an arrow of this nature would look like! My thoughts:

  • in the event that there are multiple self arrows, it’d be good to hint to the algorithm to put them in different places so they don’t overlap. This is possible for box to box arrows with flip and bow right now
  • it’d be good to be able to adjust the style (padding etc) to match whatever you might be doing with the other box to box arrows
  • probably super out of scope for now, but it’d be really great to somehow ask for as few crossing arrows as possible for aesthetics. In the meantime, maybe we’d want self-arrows to bias towards start points on the boxes that the box-to-box arrows bias away from.

My suggestion would be a perfect circle anchored at one of the corners of the box, with the same start and end padding behaviour as the box-to-box function, and maybe with its centre offset out a little along the ray intersecting the anchor corner and the centre of the box.

I’m also not sure if the preferred way to do this is a new public function, or adding a check to the box-to-box function to see if the boxes are the same. I’d suggest a new function to disambiguate between transitions from one box to itself, and from one to another box that is perfectly on top of it.

I added a test in the example here if you’d like to play with the current implementation’s output: https://github.com/gadget-inc/perfect-arrows/tree/box-to-self

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

4reactions
steveruizokcommented, Sep 18, 2020

Hey, I know what you mean! I started writing perfect-arrows for my state-charts app and this was one of the cases I started from.

Here’s the issue. Given the limited inputs to getBoxToBoxArrow, the function would have no way of knowing whether the arrow is pointing to the same box or to a different box that happens to have an identical position and size. Really, in order to know that, we’d have to know some kind of context of boxes. If we knew which boxes existed and which arrows connected which boxes, then we could identify self-to-self boxes and work on avoiding crossings, too. But all of that is a level up from what this library is aiming for, though it could build on some of the solutions that we are working on here. Maybe perfect-directed-graph? 😃

So instead, I think this would need to be its own function, getBoxToSelfArrow. My back-of-the-napkin API would be something like:

function getBoxToSelfArrow(
  x: number, 
  y: number, 
  w: number, 
  h: number, 
  options: {
    radius?: number // How big to make the loop
    angle?: number, // Where on the box the loop should start and end
    padStart?: number
    padEnd?: number
    flip?: boolean
  }
) {
  ...
  return [sx, sy, cx, cy, ex, ey, ae, as, ac]
}

image

The return values could be the same. You could then draw an ellipse that starts and ends at the given angles.

const [sx, sy, cx, cy, ex, ey, ae, as] = getBoxToSelfArrow(0,0,100,100)

ctx.moveTo(sx, sy)
ctx.arc(cx, cy, radius, as, ae)

If you did have that higher level “box manager” in your app, I think it could adjust these settings to accommodate a box with multiple self-to-self loops by setting a different angle.

for (let i = 0; i < loops.length; i++) {
  const [sx, sy, cx, cy, ex, ey, ae, as] = getBoxToSelfArrow(0,0,100,100, {
    angle: (Math.PI / 8) * i
  })

Or you could just decide to use this function instead if you had a perfect overlap.

if (boxesPerfectlyOverlap(x0, y0, w0, h0, x1, y1, w1, h1) {
  getBoxToSelfArrow(x0, y0, w0, h0)
} else {
  getBoxToBoxArrow(x0, y0, w0, h0, x1, y1, w1, h1)
}
0reactions
steveruizokcommented, Dec 23, 2021

Closing as stale. Something to come back to but no plans at the moment.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Creative Co-Op Wooden Arrow Shape Don't Look Back You're ...
Very cute, well-made, and would definitely recommend for anyone to provide themselves with a reminder as they leave their home or their therapist's...
Read more >
Arrows shouldn't bind to any shapes · Issue #4797 - GitHub
In this case, I really think removing the feature of arrow binding completely is the best solution for the product, and in-line with...
Read more >
5 Reasons Your Arrows Fly Like Crap | MeatEater Gear
The best indicator that your arrows are breaking down is if they're not grouping now like they were a few years ago. Assuming...
Read more >
What the black magic fuckery! The boxes are not really moving!
The arrows are not part of the illusion, they're just labeling it. The lines are not moving.
Read more >
Arrows - PGF/TikZ Manual
This makes it easy to vary the size of an arrow tip in accordance with the line width – usually a very good...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found