I've just started using cytoscape (with cytoscape-klay layout) to render some graphs and I'm unable to find answers to some of the questions I have:
Is there a way to left-align the graph? (graph seems to be centered horizontally, but in my use case, I need it to start from the left)
Edit: my graph is not pannable nor zoomable and panBy and shift doesn't seem to work
Is there a way to get the graph rendered without specifying the container dimensions? (right now, if I don't specify the dimensions, the canvas itself has a dimension of 0x0 and since I specify a width/height for every node, I think it should be possible)
Edit: I can't use an absolute positioned container since my view has some sticky parts. Also, I want the container dimension to be exactly what the graph needs as it is not pannable. I'm currently doing the following to accommodate both 1 and 2:
const dim = cy.$('*').boundingBox(); // get real size of graph
const container = document.getElementById('#cy');
container.setAttribute('style', `width: ${dim.w - 120}px; height: ${dim.h}px; transform: translateX(-175px)`);
Is there a way to define css in a css file or does it have to be in js?
Edit: I'm aware that I can use a js/json file - I'm wondering if I can also use a css file (I assume not, but I just want to make sure)
my nodes should be interactive (open / close) and since I work with Vue.js I prefer having my nodes as Vue components. while this seems impossible with cytoscape itself as it supports only a label for a node, I found nodeHtmlLabel package that gets me really close, it doesn't adhere to the styles that were set in js and reactivity seems to be a problem. Is there a better alternative?
Edit: I'm not asking about compound nodes. For a simple example of what I need, you can think of each node having a title and a description but only the title is visible and if you click on the node, it will open to show the description (node height would change)
can I customize the edges? (have an edge consist of a straight line connected to a bezier curved line, use my own control points, etc.) If not, how does these weights / distances work? do they work equally well for Top-Down and Left-Right graphs? (I'm trying to have something like this)
Edit: I'm aware of the current edge types, but I'm looking for something that is a merge between taxi and bezier. Since this is not currently supported, I wanted to know if there is any way to define a custom line myself
Background - I managed to get really close to the desired design with dagre-d3 but I have a problem with ranks and it seems that this package is unmaintained :(, hence I decided to look for an alternative
Related
I am trying to build a class diagram model viewer using d3.js and d3.dag
A most crucial part of this viewer is that it should be able to optimally position nodes so that we won't have link crossing (whenever possible) and plus should be able to clearly see what's connected to what
We know:
Width of each node
Height of each node
Links starting coordinate
Links ending coordinate
Links all corner coordinates
We want:
To see connections ending (Can be achieved manually moving nodes).
To minimize links crossing (If it's possible)
What I need is kinda theoretical.
Is there any known algorithm which can solve the problem above (Language does not matter, I just need theoretical reference)
Putting examples below
What's the current situation
What can I achieve by myself
What would be perfect
Example 1.
Current
Achievable
Perfect
Example 2.
Current
Achievable
Perfect
Example 3.
Current
Achievable And Perfect
Example 4.
Current
Achievable
Perfect
Example 5.
Current
Achievable
Perfect
Example 6.
Current
Perfect
Update
Traditional (node to node link ) crossing is already minimized in this case (thanks to d3-dag). The issue is that we don't have the only node to node relationship, we also have a node row to row relationship and in this case, d3-dag fails
I used d3-dag to topologically sort nodes, and then repositioned them vertically, top if odd and bottom if even
Although it's not an algorithm I was looking for, it improved the visual look of components dramatically and made much more readable
Old
New
Old
New
Old
New
I'm not sure this is still a problem, but if so, could you elaborate on what "row -> row" relationships are? Is that a strict definition on which nodes belong on which row? More recent versions of d3-dag support a rank criterion for nodes which specified relative ordering an equality constraints for a nodes row, but that may not be what you're looking for.
If you want to reposition just the edges, there may be way to pull out d3-dag's internals to just do the crossing minimization. Essentially d3 does what most layered layouts do, break an edge up to sections, and change the order of each edge in each row. After the ordering is set, it's easy to assign coordinates. If you can phrase your problem like that, you should be able to use code like this to phrase it as an integer linear program and find the optimal edge layout.
Wasn't sure if this should be on the github as an issue so I thought this was the best starting point.
I am looking to create a mind-map/network/diagram with this kind of layout:
Is this possible out of the box with vis.js networks?
the tail end seems to be a left to right hierarchical layout which is definitely a thing (though having sub sections configured differently might be harder).
Failing that has it been done in any examples you've seen
or
where should I get started with implementing something myself
I've found a way how one can create such a thing – using hidden nodes.
Create a network with nodes and edges like this:
nodes:'[
{id:1,label:"start", x:0, y:0}
,{id:2,label:"angle", x:0, y:100, hidden:true}
,{id:3,label:"angle", x:100,y:100, hidden:true}
,{id:4,label:"finish",x:100,y:200}
]
edges:[
{from:1, to:2}
,{from:2, to:3}
,{from:3, to:4}
]'
and you will get this:
This is of'course not very nice to create "fake" nodes (for instance, this is not nicely manipulatable – all those angles will change so you'd better forbid moving nodes at all) but at least allows to create a static image like you want.
PS yeap, you have to do some calculations if you want to generate such layouts automatically.
PPS here's a fiddle for you to tweak this further: https://jsfiddle.net/tjyvLbns/11/ I've already changed some options to make it look closer to what you need:
In my SVG application, I have images which the user can extend. I'd like to give controls to the user so they can bend them from the edges as well.
Here is a visual example of what a user could do.
Would love to hear suggestions on how to go about doing this.
One possible idea is that I put the image inside a path & add controls for stretching the edges of the path. However, I wonder how to stretch the image inside the path so that it consumes the whole available space.
There is no easy way to do what you want. However I can suggest two possible tricky ways:
(1) Convert it to a chain of images and apply an appropriate skew transform to each one.
(2) Use an <feDisplacementMap> filter to displace the pixels to the appropriate place.
I was wondering if there is a way of defining custom images as data-point.
For a LineGraph there is a pointSize property which sets the size of data points. (Not surprisingly).
This property can also be overridden with the series property in which you can also define a custom color.
Nonetheless, I can't see anything that would allow custom markers.
To make my question absolutely clear:
This is what I am going for: Image with an example
Two ideal solutions
Setting a property to a datapoint with class name and defining a picture for this class name in css. (to me it seems impossible since these are SVG graphics)
Adding an extra column with data-marker image source.
Although these seem perfect in theory I have no idea how to go about implementing them.
A less perfect solution could be extracting point position from SVG and using JavaScript to dynamically position divs with images (this seems very unelegant and prone to bugs)
Alternatively please recommend a js charting library that would be free and had support for such functionality.
Edit:
In the meantime I found a very good and quite inexpensive (60$ per website license) library that covers this functionality : Highcharts library But the original question is still open.
Is it possible to create a smooth animated magnifying effect (similar to the dock on Mac OS X) when hovering over nodes in a force-directed graph visualization using the D3 or GraphGL libraries?
The nodes would need to expand and displace the others around it, while maintaining the force-directed layout.
If someone could fork this to demonstrate, that would be great! Thanks
note, this is different from a simple zoom as in this question
Great question. To answer it, I implemented a D3 plugin for fisheye distortion. It's roughly based on previous work in Flare and Sigma.js, which are in turn based on the work of Sarkar and Brown, "Graphical Fisheye Views of Graphs", CHI'92.
Here's a quick demo with the Misérables dataset. View source for the code. I'll do a writeup later today when I have time.
Note: this uses a static force layout; the layout is computed on startup and doesn't change. I think this is probably what you want in conjunction with fisheye distortion, or else the distortion will compete with your ability to move nodes around dynamically. But in theory it's possible to combine them, if that's what you want.
It'd be amazing if you could do this with pure CSS, but unfortunately it looks like attributes for various SVG elements (ie, circles) aren't reachable via CSS. Specifically 'radius', but I think this is true for a whole slew of SVG element properties.
But its not super hard to do via d3. Here is my example jsfiddle. Basically you do the following:
Use transitions (see Tutorial #2 to learn how to use these). Basically do a d3element.transition().delay(300).attr(...) to make the changes happen.
To keep the 'blown up' circles from overlapping the best I could figure out to do was to modify the force layout's charge setting. Increasing the repulsive forces when circles are larger.
Hopefully thats what you are looking for...
Pure css can do this if you accept it.
.app{
-webkit-transition-property:-webkit-transform;
-moz-transition-property:-moz-transform;
-transition-property:-transform;
-webkit-transition-duration:.15s;
-moz-transition-duration:.15s;
-transition-duration:.15s;
}
.app:hover{
-webkit-transform:scaleX(1.2) scaleY(1.2);
-moz-transform:scaleX(1.2) scaleY(1.2);
-transform:scaleX(1.2) scaleY(1.2);
}
It's used on my home page tuoxie.me