I am doing research in graph theory and need to visualize graphs in real time.
(That is, if the graph data changes, its representation changes with it.)
InfoVis seems to meet that goal, but I am struggling to put together a simple 'Hello, World' page that just displays a graph on-screen with clickable nodes (where clicking causes the node to change color).
I have a working installation of JIT (the given examples work),
I just need a minimal example of InfoVis to get started,
and it is proving difficult to piece one together from the documentation.
Fiddle example.
This isn't exactly minimal, but you can probably remove some more stuff to make it so. I took code from the graph manipulation example, and removed some superfluous CSS and JS.
To get the nodes to change color, I added this line to the "onClick" function:
node.data["$color"] = "#FF0000";
The minimal elements seem to be:
a JSON data structure
instantiate the $jit.ForceDirected object, and call loadJSON
There's also a bunch of boilerplate code for cross-browser compatibility (checking for canvas support, etc).
The pared-down JSON structure looks like this:
// define three nodes
var json = [
{ // first node
// node identifier
id: "graphnode1",
// node label
name: "A graph node (#1)"
// the node's color, shape, and size
data: {
$color: "#FFFFFF",
$type: "circle",
$dim: 10
},
// this node is adjacent to nodes 2 and 3
adjacencies: [
"graphnode2",
{
nodeTo: "graphnode2",
// make the connector blue
data: {
"$color": "#0000FF"
}
},
"graphnode3",
{
nodeTo: "graphnode3",
}
]
},
// second node
{
id: "graphnode2",
name: "Another graph node (#2)"
},
// third node
{
id: "graphnode3",
name: "Another graph node (#3)"
}
];
Here's the outline of the initial code:
var json = {
// structure here
};
var fd = new $jit.ForceDirected({
// create canvas in "infovis" DOM element
injectInto: 'infovis',
// many other options here
});
fd.loadJSON(json);
Related
First of all, here's the standard JSFiddle for a Force-Directed Graph.
Here's the JSFiddle for my (perhaps misuse of) Force-Directed Graph.
My JSFiddle is throwing a larger-than-usual lump of data at Highcharts (scroll right to the bottom of the JS panel to see actual code) which may be the reason why I'm having the problem that I am having, namely that the lines joining the nodes are missing.
Other non-standard things are happening, e.g.
series: [{
dataLabels: {
enabled: true
},
data: Data.DAT,
formatting: Data.FMT
}
]
The formatting tag is permitted (according to Highcharts themselves) as it doesn't clash with anything in Highcharts API. In subsequent iterations of the main code base, I put everything into data and refer to DAT and FMT deeper in.
It is possible that something in the node management is amiss
e.options.data.forEach(function (link, i) {
if (!e.options.formatting[link.from]) {
console.log("No formatting given for FROM %s", link.from);
} else {
nodes[link.from] = {
id: link.from,
marker: {
radius: e.options.formatting[link.from].size
},
plotX: e.options.formatting[link.from].x,
plotY: e.options.formatting[link.from].y,
fixedPosition: true,
name: e.options.formatting[link.from].name,
color: e.options.formatting[link.from].colour
};
}
if (!e.options.formatting[link.to]) {
console.log("No formatting given for TO %s", link.to);
} else {
nodes[link.to] = {
id: link.to,
marker: {
radius: e.options.formatting[link.to].size
},
plotX: e.options.formatting[link.to].x,
plotY: e.options.formatting[link.to].y,
fixedPosition: true,
name: e.options.formatting[link.to].name,
color: e.options.formatting[link.to].colour
};
}
});
However, I'm at a loss trying to work out how to gets the lines to reappear, thus this posting.
The reason your lines disappear is because you are above turboThreshold. You can see this by looking at console which gives the following error:
Highcharts error #12: www.highcharts.com/errors/12
The fix for this, is either to comply with turbo threshold, that is format your series as an array (which could improve performance). Or to increase the turbo threshold. The latter will make it work, but performance will not be great.
Working example: https://jsfiddle.net/ewolden/3qLdmut8/
I'm pretty new to VisJS and attempting to visualize computer usage data. Over the past 2 months, I've collected data on how long I spend in each application on my computer in a chronological pattern. I want to create a VisJS network where each node is time spent in an application, the nodes are grouped by application, and the edges connect each node to the application I was using prior and the application I used next.
I've formatted all of my data, created a network from it, but the network always shows up in a ring. I want the different nodes to be arranged by their group - all of the "Chrome" nodes are by other "Chrome" nodes, etc.
Here's the code I'm using:
var container = document.getElementById('mynetwork');
var data = {
nodes: nodes, //about 9,000 nodes
edges: edges //about 9,000 edges
};
var options = {nodes: {
shape: 'dot',
scaling: {
min: 0,
max: 1
}
},layout: {improvedLayout: false}, physics:{enabled: true},edges: {
color:{inherit:true},
width: 0.15,
smooth: {
type: 'continuous'
}
},};
var network = new vis.Network(container, data, options);
Pretty basic, but the actual result is a mess because I have over 9,000 individual nodes. The actual result looks like this:
https://i.ibb.co/gm6d1R7/Screen-Shot-2019-04-08-at-11-23-03-AM.png
I want it to look more like the VisJS example here:
http://visjs.org/examples/network/edgeStyles/smoothWorldCup.html
The thing is, as far as I can tell, I'm using the same options as this visualization - they've just gone in and manually placed each node with coordinates, which I really can't do with 9,000 nodes. Is there a way to do this automatically without placing each node individually?
I've searched far and wide and I wasn't able to figure out what's wrong with my code. Apologies if I am missing something obvious.
I have a JSON object as follows:
var data={
"by_date":[
{"date":"2014-01-01", "count":10},
{"date":"2014-02-01", "count":20},
{"date":"2014-03-01", "count":30},
{"date":"2014-04-01", "count":15},
{"date":"2014-05-01", "count":20}
],
"by_location": {
"name":"World","children":[
{
"name":"United States", "children":[{"name":"New York", "children":[{"name":"Albany","count":5}, {"name":"NYC","count":5}]}]
},
{
"name":"Canda", "children":[
{
"name":"Alberta", "children":[{"name":"Edmonton","count":5},{"name":"Calgary","count":5}]
},
{
"name":"British Columbia", "children":[{"name":"Victoria","count":2},{"name":"Vancouver","count":8}]
}
]
},
{
"name":"China", "children":[{"name":"Beijing","count":30}]
},
{
"name":"India", "children":[{"name":"Bangalore","count":15}]
},
{
"name":"Germany", "children":[{"name":"Frankfurt","count":20}]
}
]
}
};
I want to display a line chart using data from data.by_date and a zoomable circlepack from data.by_location on the same HTML page. I have two Javascript functions by_date, which creates a line chart, and by_location, which creates a circlepack, and they both have the exact same code as Mike Bostock's line chart and zoomable circlepack examples and I call them as follows:
by_date(data.by_date);
by_location(data.by_location); // Creates circlepack, but zoom doesn't work.
The problem is that while both the line chart and the circlepack are created and displayed on the page, the zoom functionality doesn't work on the circlepack. I get the following error:
Uncaught TypeError: Cannot read property 'parent' of undefined
However, if I don't call by_date and only call by_location, it works perfectly fine.
//by_date(data.by_date);
by_location(data.by_location); // Zoom works great now!
Since by_date uses only data.by_date, and doesn't even touch data.by_location, why would commenting it out somehow make by_location work okay?
Here are fiddles demonstrating the issue:
Both line and circlepack (circlepack doesn't zoom): http://jsfiddle.net/xk5aqf8t/6/
Line chart function by_date commented (zoom works fine): http://jsfiddle.net/38sayeqa/
Note that the only difference between the two fiddles is the commented call to by_date.
Any help is greatly appreciated. Thanks in advance!
The problem in your case is that in your zoom transition you're selecting all text elements in the document, including the line chart where elements' bound data doesn't have any parent property (hence the error message).
The fix is easy. Just constrain your transition selection to the current chart. In your case you already have a selection of text elements, you can simply reuse it as demonstrated below:
// Let's keep our initial selection in the text variable:
var text = svg.selectAll('text').data(nodes);
text.enter()... // the entering selection is a subselection, so we keep it separate
// Create a new transition on the existing selection of text nodes
var transition = text.transition().duration(...); // the transition will reuse `text` selection
transition.filter(...); // don't subselect anything here
Here's a demo.
In this case i'm using JIT Hypertree. I am going to differentiate a node's color from the other's so that every node on the tree have their own color. Is there anyway to change the individual color so it would be different from other node?
I just managed to change the color of all nodes, but not individual.
Node: {
dim: 9,
color: "#009933"
},
You have to set the overridable property to true there on Node.
Node: {
dim: 9,
overridable: true
},
Then, after loading data and before drawing, iterate over the nodes and use setData to set the individual colors. Here's an example that uses random colors, but you could also plug colors into your JSON data and pull it from there:
ht.graph.eachNode(function(node) {
node.setData('color', "hsl("+Math.random()*360+",100%,50%)");
});
Now, shameless plug: I wrote a library to generate colors based on, say, IDs. So if you don't want to handpick colors and you want the colors to have a persistent relation to the data, it would help. Here's the example of using that.
ht.graph.eachNode(function(node) {
node.setData('color', $.fn.autumn.getColor(node.id));
});
I'm working on an implementation of a live-updating line graph using gRaphael which is a graphic extension of the Raphael SVG library.
I can't seem to find any examples of somebody doing this as a near-realtime updating project, which is fine. I'm assuming there's a way to call refresh on the graph with a new data set (without the need to re-initialize a whole new Raphael object each time!), but therein lies the problem:
There doesn't seem to be accurate documentation anywhere. I discovered this StackOverflow question: Graphael line chart which in turn led to this documentation project: https://github.com/kennyshen/g.raphael/tree/master/docs , but the results were cold. Using the examples provided, I ran into some errors:
the syntax r.g.linechart() used in the examples was no longer valid (where r is the Raphael object and I assume g is a gRaphael property within). Somewhere along the way somebody must have switched to properly extending the Raphael object so that r.linechart() worked.
The parameters passed into linechart() were incorrect, resulting in an undefined error again. If I passed in only the #x, #y, width, height, arrayX, arrayY parameters and dropped the chart labels, etc., I could render a plain line. But of course I need to be able to label my axes and provide a legend, etc.
Needless to say, a library without an API document isn't going to do anybody much good, but there are stalwarts out there who are willing to learn based strictly on reading the code itself. I'm not one of those. I would probably do OK with a well-commented example, preferably using live updates.
So I guess the questions are:
Does anybody know better documentation than the one I linked to?
Can someone point me to examples, documentation failing?
Can someone provide a proper itemization of the parameters that linechart() will accept?
Thanks!
For the record, here's how far I am so far:
var r = Raphael('line-chart');
// did NOT work -->
var linechart = r.g.linechart(
10,10,300,220,[1,2,3,4,5],[10,20,15,35,30],
{"colors":["#444"], "symbol":"s", axis:"0 0 1 1"}
);
// worked in a limited way, rendering a plain line with no visible labels/graph -->
var linechart = r.linechart(
10,10,300,220,[1,2,3,4,5],[10,20,15,35,30]
);
I am still trying to learn Raphael myself, but here are the primary resources I have been using: http://g.raphaeljs.com/reference.html and the same sans the "g."
here is a fiddle that pretty much pulls off an updating linechart with knockout/gRaphael, prob not the best solution, but its an idea: http://jsfiddle.net/kcar/mHG2q/
Just a note, I didn't start learning it until I combined reading with trial/error (with a lot of error), so play with the fiddle and see how things change.
but the basic code for it is like:
//constructor
var lines = r.linechart(10, 10, width, height, xVals, yVals, { nostroke: false, axis: "0 0 1 1", symbol: "circle", smooth: true })
.hoverColumn(function () { //this function sets the hover tag effect
this.tags = r.set();
for (var i = 0, ii = this.y.length; i < ii; i++) {
this.tags.push(r.tag(this.x, this.y[i], this.values[i], 160, 10).insertBefore(this).attr([{ fill: "#fff" }, { fill: this.symbols[i].attr("fill") }]));
}
}, function () {
this.tags && this.tags.remove();
});
lines.symbols.attr({ r: 3 }); //this adjusts size of the point symbols
There is a fork in GitHub that is working on the documentation and examples.
You will need to download the code and view it from you computer. It is a work in progress but it's more than you can find in the official g.Raphael page.
I also found this small post with some examples.