kieler / klayjs Goto Github PK
View Code? Open in Web Editor NEW(deprecated) KIELER's layout algorithms for JavaScript
License: Eclipse Public License 1.0
(deprecated) KIELER's layout algorithms for JavaScript
License: Eclipse Public License 1.0
Otherwise throws an error "Invalid format for 'id'. Must be a string,(...)". I guess integers are fine right.
Almost forgot to say, this repo was just what i was looking for, a minimal but highly effective elegant implementation, thanks.
See #9.
I feel specifying node label placement as a global option is not applied to the individual nodes. Check why.
'de.cau.cs.kieler.nodeLabelPlacement': 'OUTSIDE V_TOP H_CENTER',
Hi,
Please consider the following Klay JSON:
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "off_on",
"source": "off",
"target": "on",
"labels": [
{
"text": "touch",
"width": 10.140625,
"height": 5
}
]
},
{
"id": "on_off",
"source": "on",
"target": "off",
"labels": [
{
"text": "touch",
"width": 10.140625,
"height": 5
}
]
}
],
"width": 10,
"height": 10,
"children": [
{
"id": "off",
"labels": [
{
"text": "off"
}
],
"edges": [],
"width": 10,
"height": 10
},
{
"id": "on",
"labels": [
{
"text": "on"
}
],
"edges": [],
"width": 10,
"height": 10
}
]
}
When layout is applied, this yields the following kgraph:
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "off_on",
"source": "off",
"target": "on",
"labels": [
{
"text": "touch",
"width": 10.140625,
"height": 5,
"x": 37.99999952316284,
"y": 0
}
],
"sourcePoint": {
"x": 88.14062404632568,
"y": 24
},
"targetPoint": {
"x": 22,
"y": 24
},
"junctionPoints": []
},
{
"id": "on_off",
"source": "on",
"target": "off",
"labels": [
{
"text": "touch",
"width": 10.140625,
"height": 5,
"x": 37.99999952316284,
"y": 16
}
],
"sourcePoint": {
"x": 22,
"y": 27.333333333333332
},
"targetPoint": {
"x": 88.14062404632568,
"y": 27.333333333333336
},
"bendPoints": [
{
"x": 35.99999976158142,
"y": 27.333333333333332
},
{
"x": 35.99999976158142,
"y": 40
},
{
"x": 74.14062428474426,
"y": 40
},
{
"x": 74.14062428474426,
"y": 27.333333333333336
}
],
"junctionPoints": []
}
],
"width": 110.14062404632568,
"height": 53,
"children": [
{
"id": "off",
"labels": [
{
"text": "off"
}
],
"edges": [],
"width": 10,
"height": 10,
"x": 88.14062404632568,
"y": 20.666666666666668,
"$H": 26
},
{
"id": "on",
"labels": [
{
"text": "on"
}
],
"edges": [],
"width": 10,
"height": 10,
"x": 12,
"y": 20.666666666666664,
"$H": 27
}
],
"$H": 1
}
I was wondering if you could guide me as to how to interpret the x and y values of the edge labels.
When both edge labels are interpreted as being in the coordinate space (sharing the offset of) node "on", then this renders beautifully:
However it is unclear to me how to characterize the general relationship between these edge coordinates and node "on". For example, edge "on_off" has a relationship with "on" such that "on" is the source of "on_off". But this is not true of edge "off_on" - in this case node "on" is the target.
I would appreciate any guidance you can offer on how to interpret these coordinates. Thank you.
Is there a property to collapse parent/group nodes? Or is that generally done manually to the graph, before handing to layout?
Please consider the following example:
Options:
{
"algorithm": "de.cau.cs.kieler.klay.layered",
"spacing": 10,
"borderSpacing" : 10,
"labelSpacing" : 0,
"layoutHierarchy": true,
"intCoordinates": true,
"edgeRouting": "ORTHOGONAL"
}
KLay JSON:
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "a:0",
"source": "a",
"target": "a2",
"labels": [],
"sourcePort": "a_enter0",
"targetPort": "a2_enter0",
},
{
"id": "a1:0",
"source": "a1",
"target": "b",
"labels": [
{
"text": "t",
"width": 1.109375,
"height": 5
}
]
},
{
"id": "$generated_a_initial_0:0",
"source": "$generated_a_initial_0",
"target": "a1",
"labels": []
},
{
"id": "$generated_root_initial_0:0",
"source": "$generated_root_initial_0",
"target": "a",
"labels": []
},
{
"id": "a_exit0_a_enter0",
"source": "a",
"target": "a",
"sourcePort": "a_exit0",
"targetPort": "a_enter0",
"labels": [
{
"text": "t",
"width": 1.109375,
"height": 5
}
],
}
],
"width": 11.4375,
"height": 10,
"children": [
{
"id": "a",
"labels": [
{
"text": "a"
}
],
"edges": [],
"width": 6.765625,
"height": 10,
"children": [
{
"id": "a1",
"labels": [
{
"text": "a1"
}
],
"edges": [],
"width": 8.765625,
"height": 10,
"x": 0,
"y": 0
},
{
"id": "a2",
"labels": [
{
"text": "a2"
}
],
"edges": [],
"width": 8.765625,
"height": 10,
"ports": [
{
"id": "a2_enter0"
},
{
"id": "a2_exit0"
}
],
"x": 0,
"y": 0
},
{
"id": "$generated_a_initial_0",
"labels": [],
"edges": [],
"width": 4,
"height": 4,
"x": 0,
"y": 0
}
],
"ports": [
{
"id": "a_enter0"
},
{
"id": "a_exit0"
}
],
"x": 0,
"y": 0
},
{
"id": "b",
"labels": [
{
"text": "b"
}
],
"edges": [],
"width": 7,
"height": 10,
"x": 0,
"y": 0
},
{
"id": "$generated_root_initial_0",
"labels": [],
"edges": [],
"width": 4,
"height": 4,
"x": 0,
"y": 0
}
]
}
This yields the following layout:
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "a:0",
"source": "a",
"target": "a2",
"labels": [],
"sourcePort": "a_enter0",
"targetPort": "a2_enter0",
"sourcePoint": {
"x": 0,
"y": 38
},
"targetPoint": {
"x": 24,
"y": 38
},
"junctionPoints": []
},
{
"id": "a1:0",
"source": "a1",
"target": "b",
"labels": [
{
"text": "t",
"width": 1,
"height": 5,
"x": 59,
"y": 14
}
],
"sourcePoint": {
"x": 32,
"y": 20
},
"targetPoint": {
"x": 70,
"y": 20
},
"junctionPoints": []
},
{
"id": "$generated_a_initial_0:0",
"source": "$generated_a_initial_0",
"target": "a1",
"labels": [],
"sourcePoint": {
"x": 14,
"y": 20
},
"targetPoint": {
"x": 24,
"y": 20
},
"junctionPoints": []
},
{
"id": "$generated_root_initial_0:0",
"source": "$generated_root_initial_0",
"target": "a",
"labels": [],
"sourcePoint": {
"x": 14,
"y": 45
},
"targetPoint": {
"x": 27,
"y": 45
},
"junctionPoints": []
},
{
"id": "a_exit0_a_enter0",
"source": "a",
"target": "a",
"sourcePort": "a_exit0",
"targetPort": "a_enter0",
"labels": [
{
"text": "t",
"width": 1,
"height": 5,
"x": 10,
"y": 10
}
],
"sourcePoint": {
"x": 70,
"y": 26
},
"targetPoint": {
"x": 27,
"y": 55
},
"bendPoints": [
{
"x": 80,
"y": 26
},
{
"x": 80,
"y": 10
},
{
"x": 20,
"y": 10
},
{
"x": 20,
"y": 55
}
],
"junctionPoints": []
}
],
"width": 115,
"height": 82,
"children": [
{
"id": "a",
"labels": [
{
"text": "a"
}
],
"edges": [],
"width": 42,
"height": 55,
"children": [
{
"id": "a1",
"labels": [
{
"text": "a1"
}
],
"edges": [],
"width": 8.765625,
"height": 10,
"x": 24,
"y": 15
},
{
"id": "a2",
"labels": [
{
"text": "a2"
}
],
"edges": [],
"width": 8.765625,
"height": 10,
"ports": [
{
"id": "a2_enter0",
"x": 0,
"y": 3,
"width": 0,
"height": 0,
"properties": {
"de.cau.cs.kieler.portSide": "WEST"
}
},
{
"id": "a2_exit0",
"x": 0,
"y": 6,
"width": 0,
"height": 0,
"properties": {
"de.cau.cs.kieler.portSide": "WEST"
}
}
],
"x": 24,
"y": 35
},
{
"id": "$generated_a_initial_0",
"labels": [],
"edges": [],
"width": 4,
"height": 4,
"x": 10,
"y": 18
}
],
"ports": [
{
"id": "a_enter0",
"x": 0,
"y": 38,
"width": 0,
"height": 0,
"properties": {
"de.cau.cs.kieler.portSide": "WEST"
}
},
{
"id": "a_exit0",
"x": 42,
"y": 10,
"width": 0,
"height": 0,
"properties": {
"de.cau.cs.kieler.portSide": "EAST"
}
}
],
"x": 27,
"y": 16,
},
{
"id": "b",
"labels": [
{
"text": "b"
}
],
"edges": [],
"width": 7,
"height": 10,
"x": 98,
"y": 32
},
{
"id": "$generated_root_initial_0",
"labels": [],
"edges": [],
"width": 4,
"height": 4,
"x": 10,
"y": 43
}
],
}
Which when visualized as SVG yields:
You can see that the y attributes of the edge targeting port a_enter0
and the edge originating from port a_enter0
are misaligned.
Specifically, in screen coordinates, the y coordinate of target point of edge a:0 is 54 (16 + 38, which is coordinates of node a, plus target point of edge a:0). The y coordinate of target point of edge a_exit0_a_enter0 is 55. Therefore there is an off-by-one error on the coordinates of the port.
I was only able to reproduce this behavior when the layout yielded edges which were crossing, so I think that this might be related.
Please let me know what you think. Thank you.
I'm making a patching environment for real-time graphics for mobile, and I want the graph to have the autolayout so that it's always clean and consistent. This means that every time you add a new node or edges, it should apply the layout algorithm. However, when the graph gets beyond a certain size the layouting gets slower and slower until doing it every change is unrealistic.
Are there ways of only laying out certain parts? Just the parts that have changed instead of calculating the layout of the whole graph even if most of it doesn't change.
Which of the layout options is the most efficient?
How big a graph would you expect to have calculation time of less than half a second?
Thanks!
In some cases, the return value of the layout algorithm is missing sourcePoint
and targetPoint
for an edge. Here is an example input and output: https://gist.github.com/mgax/13c0d1ff02a6c9bcc5ed.
klay.layout({
graph: graph,
options: layoutOpts,
success(g) { },
error(e) { }
});
The error
function should be optional. Currently, not specifying it results in an error. The issue must be fixed in the java code.
A node in my graph has children, and I'd like to specify a minimum size for it, even if the children layout would allow it to be smaller. I've tried to specify the minWidth
and minHeight
properties but this results in an error.
Here is a minimal example: https://gist.github.com/mgax/198dca5dc60b5e5fc156 (on the left is the original graph; on the right is the output of KLayJS)
Very interesting project, it does not seem to be very open source however. Is it on purpose?
If not on purpose and if this project is supposed to be open source then where is the original source exactly? Do you have any makefiles/toolchain files to build KlayJS from the original Java source?
If we run layout on json data like below (assume edges have bendpoints as well)
{
id: 'root',
properties: { algorithm: 'de.cau.cs.kieler.fixed' },
children: [
{ id: '1', x: 100, y : 25},{id: '2', x: 200, y: 45},{id: '3', x: 200, y: 20}
],
edges: [
{source: '1', target: '2'}, {source: '1', target: '3'},{source: '3', target: '2'}
]
}
'algorithm' property is not considered and x, y positions for nodes get re-calculated.
Is this property supported for JavaScript version?
To elaborate more, what I am trying is to use klayjs to layout a workflow, and allow user to drag nodes to different position on the browser. At this point I wanted to avoid node position calculation, but want edge bend point calculation only.
is there any other way to achieve this?
I'm using klay to render large graphs (~400 nodes) and this is taking around 7 seconds. I was wondering if there is any mechanism to take into account previous positions when adding another node as to not incur the entire cost of the layout algorithm. In example if I had a graph of 400 nodes graphed and want to add another node to the graph.
I saw the interactive mode example and this seems promising, but just wanted to see if this is possible before I get started.
Setting crossMin: "INTERACTIVE"
seems to require every edge to have a bendPoints
element. There's no reason for this. Not setting it is just as fine as an empty array.
Error:
type: 'de.cau.cs.kieler.klay.gwt.client.layout.UnsupportedJsonGraphException',
text: 'Invalid format of an edge's \'bendPoints\' property.',
hi,
I'm using browserify, and I just tried this:
var klay = require('klayjs');
console.log(klay);
console.log(klay.layout);
node js output:
{ layout: [Function] }
[Function]
however, in the browser I get:
Object {}
undefined
any idea why that might be?
For those who wonder where to find the Java source.
On the Git repository server is the KIELER
project. It contains the pragmatics
subproject, where you can find the klayjs
source branch. Cloning the whole repository transfers currently circa 210 MiB.
For instance KlayLayered.java
โ a main class that contains the KLay Layered layout algorithm โ is at the location
plugins/de.cau.cs.kieler.klay.layered/src/de/cau/cs/kieler/klay/layered/KlayLayered.java
Effectively:
$ git clone http://git.rtsys.informatik.uni-kiel.de/scm/kieler/pragmatics.git
$ cd pragmatics/
$ git checkout origin/klayjs
Hello, I am getting an exception in klayjs.js and am unable to debug due to the cryptic code. I am building a graph visualization dynamically and the exception (below) occurs when I add a node to an existing graph.
I'd like to be able to see values of variables/params being passed, but unable to do so due to the cryptic/compressed JavaScript code.
I am using klay.js version 0.4.1 build 201604131004
The error reported by klayjs:
Error: {"type":"com.google.gwt.core.client.JavaScriptException","text":"(TypeError) : Cannot read property 'f' of null","stacktrace":"Unknown.x9(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.A9(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown._Q(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.aR(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.aR(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.YQ(http://localhost:63342/las/web_apps/js/klayjs/klay.js)\nUnknown.AQ(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.IP(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.layout(http://localhost:63342/web_apps/js/klayjs/klay.js)\nUnknown.d3klay.kgraph(http://localhost:63342/web_apps/js/klayjs-d3/klayjs-d3.js)"}
function x9 (a, b)
{
var c, d, e, f, g, h, i, j, k, l, m;
switch (a.g.e)
{
case 1:
d = Wv (rJ (a, (Rib (), uib)), 12);
c = Wv (rJ (d, vib), 44);
!c ? (c = new jJ) : Ckb (Ixb (Xv (rJ (d, Iib)))) && (c = lJ (c));
j = Wv (rJ (a, qib), 7);
k = MI (Bv (tv (qz, 1), Fzb, 10, 0, [j.f.i, j.i, j.a]));
if (b <= k.a)
{
return k.b
}
TI (c, k, c.a, c.a.a);
* l = Wv (rJ (a, rib), 7); // var 'l' is being returned as null
m = MI (Bv (tv (qz, 1), Fzb, 10, 0, [l.f.i, l.i, l.a]));
if (m.a <= b)
{
return m.b
}
TI (c, m, c.c.b, c.c);
...
Btw, is there un-compressed code Klayjs.js code available?
Thanks!
Please consider the following two cases.
The edge label is positioned above the last path segment, which appears correct.
The edge label is not positioned above the last path segment. It appears not toeflect the nav-open
node's updated coordinate space.
Here is the associated JSON, JSON+layout information, and resulting SVG:
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "nav-open_nav-open",
"source": "nav-open",
"target": "nav-open",
"labels": [
{
"text": "menu",
"width": 10,
"height": 5
}
]
}
],
"width": 12.171875,
"height": 10,
"children": [
{
"id": "nav-closed",
"labels": [
{
"text": "nav-closed"
}
],
"edges": [],
"width": 24.765625,
"height": 10
},
{
"id": "nav-open",
"labels": [
{
"text": "nav-open"
}
],
"edges": [],
"width": 21.953125,
"height": 10
}
]
}
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "nav-open_nav-open",
"source": "nav-open",
"target": "nav-open",
"labels": [
{
"text": "menu",
"width": 10,
"height": 5
}
]
}
],
"width": 12.171875,
"height": 10,
"children": [
{
"id": "nav-closed",
"labels": [
{
"text": "nav-closed"
}
],
"edges": [],
"width": 24.765625,
"height": 10,
"x": 0,
"y": 0
},
{
"id": "nav-open",
"labels": [
{
"text": "nav-open"
}
],
"edges": [],
"width": 21.953125,
"height": 10,
"x": 0,
"y": 0
}
]
}
<?xml version="1.0"?>
<svg class="schviz2 ng-isolate-scope" display-model="displayModel" viewBox="0 0 90.76562428474426 77.99999976158142">
<desc>Created with Snap</desc>
<defs/>
<g>
<g class="node compound">
<rect/>
<g id="nav-closed" transform="matrix(1,0,0,1,40,12)" class="node leaf highlighted">
<rect x="0" y="0" width="24.765625" height="10"/>
<text x="2.5" y="2.5" style="dominant-baseline: text-before-edge;">nav-closed</text>
</g>
<g id="nav-open" transform="matrix(1,0,0,1,41.4062,42)" class="node leaf">
<rect x="0" y="0" width="21.953125" height="10"/>
<text x="2.5" y="2.5" style="dominant-baseline: text-before-edge;">nav-open</text>
</g>
<path d="M63.35937452316284 47 L78.76562428474426 47 L78.76562428474426 65.99999976158142 L12 65.99999976158142 L12 47 L41.40624952316284 47" class="link"/>
<text x="12" y="12" dominant-baseline="text-before-edge">menu</text>
</g>
</g>
<defs>
<marker id="end" viewBox="0 -5 10 10" refX="10" refY="0" markerWidth="3" markerHeight="5" orient="auto">
<path d="M0,-5L10,0L0,5"/>
</marker>
</defs>
</svg>
Thank you for looking into this.
Hi,
I need a sub graph to have padding to ensure there will be space above it to put some other controls.
But when I set the padding to a non-zero value, the edges going into and out of that sub graph ignore it, causing a misalignment.
To see this, look at the hierarchy2 demo and add a top padding to the sub graph. You'll see that the edge placement is wrong.
Is this a bug or is there some setting I'm missing?
Thanks
I wonder if it would be possible to provide a more readable version of klayjs for development purposes.
I understand gwt has a -style PRETTY
option while compiling, maybe it can be used to also generate a klay.dev.js
file.
See: http://www.gwtproject.org/doc/latest/FAQ_DebuggingAndCompiling.html
At the moment I'm trying to load the worker with webpack which fails and the obfuscated version is impossible to debug.
Is it possible to use this library to auto-place elements like this ones?
Additionaly, it is possible to collapse groups (entities) while maintaining links like it's done here: http://live.yworks.com/yfiles-for-html/1.3/demos/complete/demo.yfiles.graph.incrementalhierarchicgrouping/index.html?
To support browser, node, and web worker, the script has to be registered in different ways. Currently, this is done in one of the java classes.
A better idea might be to use browserify. The default configuration would thus be a node module and browserify would be a part of the grunt task. A question is how the web worker fits into the picture though.
In klayjs-svg, child edges are rendered as children of the translated group. This means that the edges are layered behind other groups.
{ children:
[ { id: 'Parent1'
, children:
[ { id: 'Child1' }
]
, edges:
[ {source: 'Child1', target: 'Child2'}
]
}
, { id: 'Parent2'
, children:
[ { id: 'Child2' }
]
}
]
, edges:
[ {source: 'Parent1', target: 'Parent2'}
]
}
If I don't define the edges as child edges in the input graph, their positioning is still offset, so I'd have to walk the graph to find the edge's source node's parent's offset. This seems like a bug: edges defined on the root node should be positioned relative to the root.
{ children:
[ { id: 'Parent1'
, children:
[ { id: 'Child1' }
]
}
, { id: 'Parent2'
, children:
[ { id: 'Child2' }
]
}
]
, edges:
[ {source: 'Parent1', target: 'Parent2'}
, {source: 'Child1', target: 'Child2'}
]
}
Thanks for developing this library, its potential is huge!
I've been playing around with the options, and I'm wondering if it's possible to use multiple directions within the same layout?
I.e. in the following example:
The root level direction (between Chippy.. and Namespace) would ideally be downwards, then the direction within them should be rightwards, this way it'd be evenly spaced out down/rightwards.
The same goes for the edges, i.e. is it possible to have the edge from 'dqw' to 'Method 1' route to the left, so it doesn't have to go all the way around?
Lastly, I was wondering if it's possible to have 'Deb' show up on the same row as 'Method 1' and 'dqw'?
Thanks! My options are:
var defaultOptions = {
edgeRouting: 'POLYLINE',
direction: 'RIGHT',
crossMin: 'INTERACTIVE',
nodeLayering: 'INTERACTIVE',
nodePlace: 'NETWORK_SIMPLEX',
fixedAlignment: 'BALANCED',
cycleBreaking: 'INTERACTIVE',
thoroughness: 2500,
spacing: 25,
borderSpacing: 35,
algorithm: 'de.cau.cs.kieler.klay.layered',
feedBackEdges: false,
layoutHierarchy: true
};
Is it possible to keep the node positions from an input graph, and only perform edge routing?
GTW 2.8 supports Java 8.
Could you provide a new release with the latest features?
Is there a way to specify a maximum graph width, beyond which the nodes are wrapped so that they stay inside the bounds? Kind of like word wrap in text editors.
Hello,
I am trying to find a way to prompt klay to layout an edge that originates in a parent node and targets a descendant node, such that the edge exits and re-enters the parent node.
My use case is as follows. In the Statecharts formalism, there are two varieties of transitions: internal and external. This distinction is relevant when a transition originates from a parent state and targets a substate. The difference between these two transition types, semantically, is that when a transition is taken, an external transition causes the source state to be exited and re-entered, while the internal transition does not cause the source state to be exited.
I have found that the KlayJS default layout works very well for internal transitions:
I have tried to force klay to exit the parent node by creating an invisible "pseudonode" with width and height 0, however this results in a graphical artifact, as a bend point is created which overlaps with the edge originating from the pseudonode. You can see the results below:
Input KGraph JSON:
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "a_a2",
"source": "a",
"target": "$generated-1",
"labels": [
{
"text": "t1",
"width": 3.109375,
"height": 4.5
}
],
"$type": "hyperlink"
},
{
"id": "a2_b",
"source": "a2",
"target": "b",
"labels": [
{
"text": "t2",
"width": 3.109375,
"height": 4.5
}
]
},
{
"id": "b_c",
"source": "b",
"target": "c",
"labels": [
{
"text": "t3",
"width": 3.109375,
"height": 4.5
}
]
},
{
"id": "$generated-1_a2",
"source": "$generated-1",
"target": "a2"
}
],
"width": 11.4375,
"height": 9.5,
"$type": "scxml",
"children": [
{
"id": "a",
"labels": [
{
"text": "a"
}
],
"edges": [],
"width": 6.765625,
"height": 9.5,
"children": [
{
"id": "a1",
"labels": [
{
"text": "a1"
}
],
"edges": [],
"width": 8.765625,
"height": 9.5,
"x": 0,
"y": 0
},
{
"id": "a2",
"labels": [
{
"text": "a2"
}
],
"edges": [],
"width": 8.765625,
"height": 9.5,
"x": 0,
"y": 0
}
],
"x": 0,
"y": 0
},
{
"id": "b",
"labels": [
{
"text": "b"
}
],
"edges": [],
"width": 7,
"height": 9.5,
"x": 0,
"y": 0
},
{
"id": "c",
"labels": [
{
"text": "c"
}
],
"edges": [],
"width": 6.765625,
"height": 9.5,
"x": 0,
"y": 0
},
{
"id": "$generated-1",
"$type": "pseudonode",
"width": 0,
"height": 0,
"edges": [],
"x": 0,
"y": 0
}
]
}
Kgraph after layout:
{
"id": "root",
"labels": [
{
"text": "root"
}
],
"edges": [
{
"id": "a_a2",
"source": "a",
"target": "$generated-1",
"labels": [
{
"text": "t1",
"width": 3,
"height": 4,
"x": 23,
"y": 56
}
],
"$type": "hyperlink",
"sourcePoint": {
"x": 87,
"y": 46
},
"targetPoint": {
"x": 10,
"y": 36
},
"bendPoints": [
{
"x": 96,
"y": 46
},
{
"x": 96,
"y": 63
},
{
"x": 16,
"y": 63
},
{
"x": 16,
"y": 36
}
],
"junctionPoints": []
},
{
"id": "a2_b",
"source": "a2",
"target": "b",
"labels": [
{
"text": "t2",
"width": 3,
"height": 4,
"x": 64,
"y": 18
}
],
"sourcePoint": {
"x": 37,
"y": 26
},
"targetPoint": {
"x": 77,
"y": 26
},
"junctionPoints": []
},
{
"id": "b_c",
"source": "b",
"target": "c",
"labels": [
{
"text": "t3",
"width": 3,
"height": 4,
"x": 133,
"y": 28
}
],
"sourcePoint": {
"x": 123,
"y": 36
},
"targetPoint": {
"x": 146,
"y": 36
},
"junctionPoints": []
},
{
"id": "$generated-1_a2",
"source": "$generated-1",
"target": "a2",
"sourcePoint": {
"x": 10,
"y": 36
},
"targetPoint": {
"x": 68,
"y": 36
},
"junctionPoints": []
}
],
"width": 163,
"height": 74,
"$type": "scxml",
"children": [
{
"id": "a",
"labels": [
{
"text": "a"
}
],
"edges": [],
"width": 47,
"height": 46,
"children": [
{
"id": "a1",
"labels": [
{
"text": "a1"
}
],
"edges": [],
"width": 8,
"height": 9,
"x": 10,
"y": 10
},
{
"id": "a2",
"labels": [
{
"text": "a2"
}
],
"edges": [],
"width": 8,
"height": 9,
"x": 28,
"y": 21
}
],
"x": 39,
"y": 10,
"$H": 25
},
{
"id": "b",
"labels": [
{
"text": "b"
}
],
"edges": [],
"width": 7,
"height": 9,
"x": 116,
"y": 31
},
{
"id": "c",
"labels": [
{
"text": "c"
}
],
"edges": [],
"width": 6,
"height": 9,
"x": 146,
"y": 31
},
{
"id": "$generated-1",
"$type": "pseudonode",
"width": 0,
"height": 0,
"edges": [],
"x": 10,
"y": 36
}
],
"$H": 1
}
I was wondering if there is a better way to use the klay API to support this use case? Thank you for your guidance on this.
Setting layoutHierarchy
to false
results in short hierarchical edges not being imported by the JsonGraphImporter#643
. Theoretically such edges would be supported in this mode (external port dummies would be introduced). The workaround is to set layoutHierarchy
to true.
The problem occurs when I have a KGraph that has edges between parent and Children Nodes as seen below (the edges labels are the blue ones):
The initial graph is:
{
"id": "root",
"children": [
{
"id": "bar-chart",
"labels": [
{
"text": "bar-chart",
"width": 63,
"height": 10
}
],
"width": 130,
"height": 70,
"ports": [
{
"id": "dataColumns_bar-chart_input",
"properties": {
"portSide": "WEST"
},
"labels": [
{
"text": "dataColumns",
"width": 55,
"height": 10
}
],
"height": 10
},
{
"id": "xLabels_bar-chart_input",
"properties": {
"portSide": "WEST"
},
"labels": [
{
"text": "xLabels",
"width": 35,
"height": 10
}
],
"height": 10
}
],
"properties": {
"portConstraints": "FIXED_SIDE",
"portLabelPlacement": "OUTSIDE",
"nodeLabelPlacement": "V_TOP",
"portAlignment": "CENTER",
"portSpacing": 3,
"borderSpacing": 40,
"labelSpacing": 6
},
"children": [
{
"id": "chart1",
"labels": [
{
"text": "base-chart",
"width": 70,
"height": 10
}
],
"width": 130,
"height": 85,
"ports": [
{
"id": "dataColumns_chart1_input",
"properties": {
"portSide": "WEST"
},
"labels": [
{
"text": "dataColumns",
"width": 55,
"height": 10
}
],
"height": 10
},
{
"id": "xLabels_chart1_input",
"properties": {
"portSide": "WEST"
},
"labels": [
{
"text": "xLabels",
"width": 35,
"height": 10
}
],
"height": 10
},
{
"id": "type_chart1_input",
"properties": {
"portSide": "WEST"
},
"labels": [
{
"text": "type",
"width": 20,
"height": 10
}
],
"height": 10
}
],
"properties": {
"portConstraints": "FIXED_SIDE",
"portLabelPlacement": "INSIDE",
"nodeLabelPlacement": "V_TOP",
"portAlignment": "CENTER",
"portSpacing": 3,
"borderSpacing": 12,
"labelSpacing": 6
}
}
]
}
],
"edges": [
{
"id": "con1",
"labels": [
{
"text": "con1",
"width": 20,
"height": 10
}
],
"source": "bar-chart",
"sourcePort": "dataColumns_bar-chart_input",
"target": "chart1",
"targetPort": "dataColumns_chart1_input"
},
{
"id": "con2",
"labels": [
{
"text": "con2",
"width": 20,
"height": 10
}
],
"source": "bar-chart",
"sourcePort": "xLabels_bar-chart_input",
"target": "chart1",
"targetPort": "xLabels_chart1_input"
}
]
}
And the initial options:
var layouter = klay.d3kgraph()
.size([this.dataflowViewWidth, this.dataflowViewHeight])
.transformGroup(root)
.options({
layoutHierarchy: true,
intCoordinates: true,
direction: 'RIGHT',
edgeRouting: 'ORTHOGONAL',
nodeLayering: 'NETWORK_SIMPLEX',
nodePlace: 'BRANDES_KOEPF',
crossMin: 'LAYER_SWEEP',
algorithm: 'de.cau.cs.kieler.klay.layered'
});
When i change the option portLabelPlacement in parent node to 'INSIDE' I got this other issue: edges labels are correctly located, but the source points of edges are wrong
When there are no those edges everything is correctly located:
When using the SPLINES edgeRouting option in a big graph with ports, some of the edges take spiky detours, and get a seemingly unnecessary number of bendPoints. This makes the edges appear jagged with spikes in the opposite direction:
If I remove the first two cubic instructions (i.e. the first 6 bendPoints) for these particular examples, the lines appear more smooth.
I've been using the plainjslinker nightly, and I follow the instructions from here to render the lines. Are these still up to date with the latest version?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.