Problem with z-index

570 views
Skip to first unread message

Stefan Zschocke

unread,
Jun 21, 2018, 6:00:04 AM6/21/18
to JointJS
My problem is, that I have links running through elements as in the picture below.
I would like to have the element-label at higher z-order of the link, but this obviously is not easily achieved, as svg does not support z-order and draws the elements in the order in which they appear in the DOM.
If the element were above the link, then the link were not visible at all.
I know, that an alternative could be, to not draw the line, which runs thru the element as link, but instead as part of the element. Then I probably could arrange the order of the element content, achiieving that the text is rendeerd after the line.
However the number of links running thru the element is dynamically determined (may be more than one), which makes it complicated, and I already have my solution with the links, with the only drawback that it runs through the text.
On stackoverflow I found mention of the <use.../> tag as possible solution, but don't know how I can append this tag to the svg being created by jointjs.(https://stackoverflow.com/questions/17786618/how-to-use-z-index-in-svg-elements)
Is there a way to append use-tag?


Roman Bruckner

unread,
Jun 21, 2018, 10:37:12 AM6/21/18
to joi...@googlegroups.com
Hi Stefan,

You can have <use/> tag as part of the element/link markup (i.e. it's same as e.g a rectangle).

In your case, I think you'd rather put all the usages of the text on top of all elements and links (not part of an element).

                function updateOverlays(paper, overlayContainer, selector) {
                    overlayContainer.empty();
                    V(paper.viewport).append(overlayContainer);
                    paper.model.getElements().forEach(function(model) {
                        var view = model.findView(paper);
                        var nodes = view.findBySelector(selector);
                        var position = model.position();
                        nodes.forEach(function(node) {
                            V('use').attr({
                                'xlink:href': '#' + node.id,
                                'pointer-events': 'none',
                                'x': position.x,
                                'y': position.y
                            }).appendTo(overlays);
                        })
                    })

                }

                var overlays = V('g').addClass('overlays');                
              updateOverlays(app.paper, overlays, 'text');

Here in the example, I added the group of overlays in the viewport (so they are automatically scaled when the paper is zoomed) and after all elements and links.

Best,
Roman

--

---
You received this message because you are subscribed to the Google Groups "JointJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jointjs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--

Stefan Zschocke

unread,
Jun 22, 2018, 7:32:26 AM6/22/18
to JointJS
Hi, thank you very much for this very instructive example.
I have 2 follow-up questions:
1 What happens, when new elements and links are added to the graph by the user. Won't these new elements be appended behind the overlays in the viewport? How can I make sure that the overlays element is alwas last in the svg?
2 When the user moves an element, I think I must change the position of the related use-element as well. I guess I need to listen to the change-events of the elements.In order to keep an established relation between the element and the use-element, would it make sense to have a custom element view, which keeps a reference to the V("use") object?

Thanks, Stefan

Roman Bruckner

unread,
Jun 26, 2018, 11:24:43 AM6/26/18
to joi...@googlegroups.com
Hi Stefan,

right, the best approach as far as I can see would be as follows.

1. append an `SVGGroup` (overlays) to the `paper.svg` (so overlays are always on top of the viewport) `paper.overlays`
2. set "pointer-events=none" on this group (so no events are captured by these overlays)
3. on paper events `translate` and `scale` set the current transformation matrix of the paper to the group (V(paper.overlays).transform(paper.matrix(), { absolute; true }));
4. create custom element view that creates and keeps a reference to V('use'). It should update and remove the V('use') on specific model events. 

Best,
Roman


--

---
You received this message because you are subscribed to the Google Groups "JointJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jointjs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Stefan Zschocke

unread,
Jun 26, 2018, 1:31:22 PM6/26/18
to JointJS
Thank you for your reply.
In the meanwhile I decided, that it is better to draw the line, which go from the left port to the right port of an element as part of the element and not as link.
As the number of those lines is dynamic, same as the number of ports, I first considered doing a custom implementation, similar to your ports-api. But then I noted, that the port-api is quite complicated, and also that it essentially does what I need, so I defined a new port group 'line', which draws lines instead of circles.
This only left to re-arrange the svg elements, so that the text-element is drawn after the ports.
Therefore I defined a custom ElementView and in my overload of Render, I first call the base Render, and then I manipulate the vel of the view, moving the text-element to the last position in the children collection.

Roman Bruckner

unread,
Jun 26, 2018, 1:58:42 PM6/26/18
to joi...@googlegroups.com
Hi Stefan,

I don't think a custom view is necessary in this case. Please take a look at the `z` attribute for the ports.


Best,
Roman

--

---
You received this message because you are subscribed to the Google Groups "JointJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jointjs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Stefan Zschocke

unread,
Jun 27, 2018, 3:08:28 AM6/27/18
to JointJS
Hi, thank you for your reply. I knew the z-index feature of the port, but was not aware, that it influences the rendering order with respect to the static parts of the element (in the case of this example the inner rectangle).
I thought it would just sort the ports.

Reply all
Reply to author
Forward
0 new messages