Two `dygraphs` with synchronized crosshair - javascript

I have implemented two dygraphs with custom option verticalCrosshair : true here:
https://rawgit.com/danielkrizian/dygraphs/master/tests/synchronize-Crosshair.html
When I hover over any of the graphs at a particular x point, I want all graphs to display the vertical crosshair at that point.
So far I've been able to get this working on the top graph (gs[0]) like this:
highlightCallback: function(e, x, pts, row) {
var sel = gs[0].getSelection();
gs[1].setSelection(sel);
},
Nothing happens when I hover over the bottom graph. How to generalize it with for loop over all graphs?

You should put the dygraphs objects in an array and loop over it in your highlightCallback, updating the selection in all the dygraphs other than the one generating the event.
One complication is that highlightCallback doesn't get the dygraph object as a parameter. This is an oversight in the API which I hope to fix in dygraphs 2.0. You can work around it by capturing the relevant Dygraph object in a closure when you set highlightCallback.
See the synchronize demo for some inspiration.

I've solved this with:
highlightCallback: function(e, x, pts, row) {
for (var j = 0; j < gs.length; j++) {
gs[j].setSelection(row);
}
},
See the graphs and source at:
https://rawgit.com/danielkrizian/dygraphs/master/tests/synchronize-Crosshair.html

I have had both of these features up and working for nearly a year. I didn't originate the code, but just did just some editing in an effort to get the labelFollow bit working the way that I liked. I followed the original author(s) and stuffed the code in the library, not in a mere callback in a Dygraph() options argument, but I did not put the verticalCrosshair snippets in a plug-in as I don't know how to write those yet. However, the labelFollow stuff is in the plug-in legend.js, as that's what the original author had done.
As for the code for the verticalCrosshair option, I got it from the apparently esteemable DJCOMXA--- http://www.pixeltradr.com/dygraphs/dygraph.js. Just search for "verticalCrosshair" and you'll find where two tiny snippets have been added to that script.
To complete the verticalCrosshair option it's necessary of course to also add to dygraph-options-reference.js as follows:
// Credit due to DJCOMXA.
"verticalCrosshair": {
"default": "false",
"labels": ["Interactive Elements"],
"type": "boolean",
"description": "Shows vertical line on highlighted point."
},
Now for the other matter of the labelFollow, for proof of prior work on labelFollow it suffices to go to the Google group. You can then click on the link at the very bottom of that page to see a graph that shows both the verticalCrosshair and the labelFollow (the latter being, I believe, the work of "wootwoot" who I more or less copied). Similarly, replace "synchronize-Charts" in that URL for that graph with "customLabel_Crosshair" and you'll be taken to a prettier example (I think that I'm limited as to the number of links that I can provide, hence the URL re-construction instructions).
I can't now figure out how I got the original labelFollow code. Whatever, I found some modifications to legend.js (and of course dygraph-options-reference.js) by wootwoot and edited them.
I must say that I wrote to danvdk at the gmail address that he provided at the top of dygraph.js, to suggest the utility of these changes, and it was bounced as I was not a member of the club.
Regarding taking inspiration from the Dygraphs sychronization example (the "synchronize demo" link that danvk provided), take your inspiration from it cautiously. Right now it's giving me fits.
Try this: upon page load go to any of the four graphs and in the middle at a skinny section do a zoom in (click drag from left to right); then double-click.
What happened? You zoomed in and the traces filled the graph vertically, but for a little bit of padding--- automatic scaling. And then upon zooming out with the double-click everything appeared to be as before. Ahh... but it isn't. Now move to any OTHER of the four graphs and repeat the first step... zoom in at a the same skinny spot (the data happen to be the same for each of these graphs). Notice that the automatic vertical scaling is missing. And that's a permanent condition until you reload the page.

Related

Vis.js: Lessen layout noise for multiple central nodes (radial force)

I'm working with vis.js to display some graphs. The problem is that layouts with multiple central nodes get noisy (the central nodes' neighbours overlap). A layout similar to the attached image is desirable.
Is it possible to achieve this using vis.js?
Looks like there is an option that should solve your issue (I've found it after playing with physicsConfiguration like I suggested earlier):
physics has avoidOverlap property (float between 0 and 1) that can be used like this:
var options = {
...
physics: {
barnesHut: {
avoidOverlap: 0.5
},
...
}
}
If you try it in the configuration demo, you'll see that with avoidOverlap equal to 0 it's quite possible to drag and move nodes so that those overlap edges and the network stays in that position:
but once we increase this value, nodes start to be bounced from edges and can't really stay in that position:
Note though, that this option doesn't prevent edge-edge crossing, only edge-node overlapping (see physics/barnesHut/avoidOverlap). The physics docs page doesn't contain the word "cross" at all and each occurance of "overlap" is about edge-node thing.
So this will make the layout less noisy, but won't eliminate crossed edges.

Vis.js not showing graph when many nodes are added

I am making a web app to show relationships between items using Vis.js, everything works perfectly fine until I get to the point where I need to display ~260 nodes with ~1200 edges between them.
Once I get to that amount of nodes, the graph just shows a blank space and a blue line, nothing else. As soon as I try to zoom it, the line disappears and it's all white.
When I look at the position of the nodes I can see that many of them are in negative or very big x, y positions (generally -300 for x and around 478759527705558300000 for y).
I have tried, to no avail, to disable physics. The graph is in hierarchichal mode, with levels manually set in the code, but the levels are correct.
Network options (the improvedLayout option was just a possibility I found on the internet; it works just the same if I remove it):
var options = {
layout: {
improvedLayout: false,
hierarchical: {
direction: direction,
sortMethod: "directed"
}
}
}
Screenshot:
I have hierarchical layout graph which consists of around 615 nodes and 614 edges (excluding 40 odd cluster nodes, some of them cluster of clusters). I landed into same problem with visjs.
One quick thing which helped me to get over this problem was to explicitly call network.stabilize() method with an argument specifying number of iterations. Default iterations are 1000. I passed 10000 and graph stabilized it self nicely. It took a few more seconds, i was fine with that. But stabilization times shoots up as number nodes increased to ~1000. So i started looking into visjs code for solution.
While looking in visjs code, i found that inside function setupHierarchicalLayout() there is a call to _condenseHierarchy().
This method tries to minimize white spaces between nodes and edges (yet to understand the code fully). _condenseHierarchy() modifies coordinates of a node. See Y coordinate before and after call to _condenseHierarchy() below:
(this.body.nodes["node-11"]).y
1530
(this.body.nodes["node-11"]).y
64920
When a node gets a distant position it takes lots of iterations (in stabilize) to bring it closer together with other nodes in graph. I disabled _condenseHierarchy() and got the graph displayed nicely.
I'm sure disabling _condenseHierarchy() would bring in some other issues as i proceed further. I am going to spend some more time to understand and experiment with _condenseHierarchy().
To solve this problem, you can adjust hierarchical layout parameters, such as nodeSpacing, levelSeparation and treeSpacing. Here is an example hierarchicalLayoutWithoutPhysics

moving path to front changes selection?

i'm struggling to understand the following behaviour: i have two maps (based on topojson-data, visualised through d3), and on mouseover over certain parts of map1, the corresponding parts of map2 should light up. i got it to work with changing the style (opacity or fill), but now i wanted to highlight the borders of each map-part.
as seen for instance here one needs to move the specific path to the front to make all the borders visible. this is no problem for the area where i move the mouse across (using this), but when i select the corresponding part of the other map, it works one time and after that other parts get selected - so my guess is something is messing with the selection.
here is the code:
.on("mouseover",function(d){
var old=d.properties.iso; //this is the identifying number of the map-part(s)
sel=svg2.selectAll("path")
.data(datastore2015.features)
.filter(function(d){return d.properties.iso==old;})
.node(); //here the corresponding part(s) get filtered
d3.select(sel.parentNode.appendChild(sel)).classed("high2",true); //and this moves it to front and highlights the borders
on mouseout, it just resets:
.on("mouseout",function(d){
svg2.selectAll("path").classed("high2",false);
when i log the data to the console it seems that each mouseover moves +1 entry through the dataset, starting by the first entry the mouse moved over. i could not figure out why this happens and how to avoid it.
i'd appreciate any ideas you could give me, mainly i'd like to understand what's going wrong and why.
thanks
so i found my error, calling the data-variable once again seems to have messed things up - somehow i was under the impression that i need it, but it works just fine this way:
sel=svg2.selectAll("path").filter(function(d){return d.properties.iso==old;}).node();
d3.select(sel.parentNode.appendChild(sel)).classed("high2",true);
sorry for the bother, i didn't see this possibility before.

Highcharts Column Graph with background color?

I'm trying to make a column graph in Highcharts and it's not working out too hot. I'm essentially trying to give the column a background color that the data point can overlay. I want the effect of stacking without actually stacking if that makes sense. Any thoughts on what I can do?
Essentially I want it to look like a progress bar... there should be a distinct coloring between the top of the bar and the top of the graph itself. I've already tried stacking: percentage, but to no avail. Thoughts?
There are three options that come to mind:
1) To achieve the 'effect' of stacking, actually stack it: use a dummy series with a color set to the background color that you want, and set with values to fill the gap from the actual data.
Example:
http://jsfiddle.net/jlbriggs/Zf8C7/5/
[[edit for questions
The order of the series does not matter for this to work, and neither does the legendIndex.
What does matter, if you are using multiple series, is the stack property for each series - http://api.highcharts.com/highcharts#series.stack
Each group will need its own stack, and the dummy series and real series within each group need to be assigned to the same stack.
In addition, you need to have one overall max value.
Updated example:
http://jsfiddle.net/jlbriggs/4d9tm6b8/4/
(keep in mind, there are much smoother methods to process and build your data - this is a quick and dirty example whose purpose is to show how to properly use the stack property to do what you need)
]]
2) plotBands, as mentioned above
3) using the alternateGridColor property and set your data to skip an x axis
value between each point.
Reference:
- http://api.highcharts.com/highcharts#xAxis.alternateGridColor

Tricky raphael svg animation

I've created a 'donut' chart originally from this jsfiddle, using raphael.
I have tweaked this script to suit my needs and currently have this being rendered.
My aim is to animate each slice (at the same time); for example make the blue slice grow to 60%; and the red slice shrink to 40%.
I have been able to redraw the slices by removing the existing one and quickly re-rendering a new one with adjusted values (e.g. 51, 49). But the problem here is that it is instant.
My question is,
(a) Can I animate this without the need to redraw the object (and how)?
(b) If not, how I can animate this effect using a redraw logic?
Yes. There is an example of doing this very thing on the Raphael demos page where you got the pie chart. See the Growing Pie demo.
You should separate the code in which you generate the path into a standalone function so you can use it later to return new paths. In order to use animate(), you'll need to define a function on the customAttributes object; it should return (at least) an object with the path property set to your slice's new path.
Since you have labels, you'll probably want to modify the code such that the pie slices expand/shrink relative to their center, so that you don't have to move the labels, too, since the labels are centered on their slice's "axis."
Update
Here's a JSFiddle with a simple example, pretty much the same as Dmitri's Growing Pie demo, except more like your chart. I export a setValue() method to change slice sizes and call it when the page loads. See his blog post about adding customAttributes, too.
In my last paragraph above, I was off the mark a bit. Your chart wasn't the one with labels; I had them mixed up. Also, it would be harder to keep slices centered, so I didn't do that after all. The animate() function sets each segment to its new starting and ending points on the circle, and Raphael figures out the intermediate points. As you can see, you can pass multiple arguments in an array.
this.customAttributes.slice = function(a0, a1) { /*...*/ }
// ...
chart.push(paper.path().attr({slice:[0, Math.PI/2 ]})
Can't see all the fiddle because I'm on iPod however it sounds like you need to have an animate call inside a function that you will need to write
Use the callback parameter that calls the function it sits inside.
Code your recursively called function so it eventually completes when all the work is done.
Each call to the function will happen at the end of every elapssed time interval you specify...

Categories

Resources