Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Safari doesn't render link arrow markers after loading data #2328

Open
frnora opened this issue Sep 7, 2023 · 10 comments
Open

[Bug]: Safari doesn't render link arrow markers after loading data #2328

frnora opened this issue Sep 7, 2023 · 10 comments
Labels

Comments

@frnora
Copy link

frnora commented Sep 7, 2023

What happened?

Hi,

There is some issue with the markers (not) rendering on Safari, take a look at this image directly from the demo page:
Screen Shot 2023-09-07 at 19 05 01

The markers appear again when you reconnect the link (or create a new one) but it doesn't work after loading the data. Any ideas?
(Safari Version 16.6)

Version

3.7

What browsers are you seeing the problem on?

Safari

What operating system are you seeing the problem on?

Mac

@frnora frnora added the bug label Sep 7, 2023
@kumilingus
Copy link
Contributor

When you are using Safari, there is a bug where SVG Markers are not rendered if they are added asynchronously in the next animation frame.

Here is the minimal reproducible case: https://jsfiddle.net/kumilingus/k90h2Lt1/

The issue has been reported. We are currently waiting for the Safari team to address it.

In the meantime, you need to apply a workaround - there are a lot of ways, but it's important to somehow trigger the browser update of the SVG again.

  • The issue is not happening when the async paper option is set to false
  • The issue can be resolved for instance by hiding the paper and showing it again (see below).
paper.freeze();
graph.fromJSON(graphJSON);
paper.unfreeze({
    afterRender: function() {
        paper.el.style.display = 'none';
        requestAnimationFrame(() => paper.el.style.display = '');
        paper.unfreeze();
    }
});

@frnora
Copy link
Author

frnora commented Sep 27, 2023

The above code doesn't fire afterRender for me, tho. In update updateViewsAsync the condition checking for the id of the update evaluates to false (update.id is null). The subsequent calls don't get the afterRender fn anymore in the opt object.

@kumilingus
Copy link
Contributor

If the graph is empty, the afterRender callback will not trigger.

You need to check if the graph is empty or check if there are any updates scheduled.

@frnora
Copy link
Author

frnora commented Sep 27, 2023

Am I misunderstanding this?
Can the graph be empty after fromJSON if the json contains cells? I.e.:

paper.freeze();
graph.fromJSON(graphJSON);
console.log(graph.getCells()); // <- correctly logs the cells
paper.unfreeze({
    afterRender: function() {
        paper.el.style.display = 'none';
        requestAnimationFrame(() => paper.el.style.display = '');
        paper.unfreeze();
    }
});

@kumilingus
Copy link
Contributor

No. Empty in the sense of graph.getCells().length > 0.

@frnora
Copy link
Author

frnora commented Sep 27, 2023

Eh... so it should work in the above example if the graph has cells?
paper._updates.priorities.some(updates => !joint.util.isEmpty(updates)); returns true.

I am not using the viewport options, btw, if there is any connection.

@kumilingus
Copy link
Contributor

The hasScheduledUpdates() method has been already added to JointJS.

if (paper.hasScheduledUpdates()) {
  paper.unfreeze({
      afterRender: function() {
          paper.el.style.display = 'none';
          requestAnimationFrame(() => paper.el.style.display = '');
          paper.unfreeze();
      }
  });
} else {
    paper.el.style.display = 'none';
    requestAnimationFrame(() => paper.el.style.display = '');
    paper.unfreeze();
}

If this is not helping, please provide steps to reproduce.

@frnora
Copy link
Author

frnora commented Sep 27, 2023

Sadly, that doesn't work. Same problem: gets to the if condition but then the afterRender doesn't fire.

I will try to come up with a case to reproduce.

@frnora
Copy link
Author

frnora commented Sep 27, 2023

I narrowed down the problem: It doesn't fire because there is another call coming in right after the load to set the router (the call may or may not happen but in my test cases it always happens) so it is:

  1. app.load() (freeze, fromJSON, unfreeze with afterRender)
  2. app.setDefaultRouter(...) which looks like this:
// ... some other stuff that doesn't matter
paper.freeze();
links.forEach(link => {
    link.findView(paper).requestConnectionUpdate();
});
paper.unfreeze();

This blocks the afterRender from the first (load's) unfreeze call. Should it?

@kumilingus
Copy link
Contributor

paper.unfreeze({ afterRender: () => console.log('Hello'); });
paper.unfreeze();

"Hello" is never called. The second unfreeze cancels the first call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants