I'm building a pie chart at the moment, and it's mostly done.
Anyway, I'm trying to implement some hover effects on each pie slice, but I've come across a problem I'm unable to solve. When you hover over an element the text increases in size, and also uses a filter to add a black background. The issue with this is that the text is sometimes being hidden behind other elements, as if those elements are on top of it. My best solution to fix this was adding visibility and making it !important.
.pieChart svg>g text.hover {
font-size: 1.3em;
fill: #fff;
filter: url(#pieTextFilter);
visibility: visible !important;
}
This, however, doesn't solve my problem.
Here is a jsfiddle that represents the problem (hover you mouse of slice 4): http://jsfiddle.net/tinygram/22o1epyp/3/
If you're familiar with D3, it might be important to note that this happens only after I update the graph. If you look at the bottom of my jsfiddle, you'll see that I'm starting the graph and then running it again with some updated data. I have noticed that this adds a new and at the end of the svg in the dom. I honestly don't know if this is important, but I thought I should mention it.
As #LarsKotthoff mentions in his comment, it's all in the order. You initially build a pie chart with 4 slices, you then add a 5th slice. So the enter selection first adds 4 slices and 4 labels. On the addition of the 5th slice, it updates the first 4 slices/labels and enters a 5th slice/label. This addition of a 5th slice is then on top of the 4th label.
See this fiddle. The problem goes away because I've invoked the exit:
tests(data);
tests({});
tests(data2);
A better fix might just be to remove all the texts before update:
tests(data);
d3.selectAll('text').remove();
tests(data2);
Related
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.
Im using this great article to produce a venn diagram with D3.
http://www.benfrederickson.com/venn-diagrams-with-d3.js/
It looks great but on occasion I get bubbles overlapping the the labels become hidden. Is there a way to make sure the text element is always on top? (see the picture below.. label A needs to be on top of circle B.
I found this good article but im struggling in how to implement this in the venn.
How can I bring a circle to the front with d3?
You should grab the latest code from master: this commit should fix the issue you had there https://github.com/benfred/venn.js/commit/4cb3bbef65b5b3c3ce02aee7d913e8814e898baf
Instead of having the 'A' label be overtop of the 'B' circle - it willnow move the label so that its in the certain of the 'A' region that isn't overlapped with 'B'. Some details are in this issue here: https://github.com/benfred/venn.js/issues/18
You might find it easier to work in actual layers. You can use g elements to create them. For example:
var lowerLayer = svg.append('g');
var upperLayer = svg.append('g');
Now anything you append to upperLayer will appear above anything you append to lowerLayer because the two g elements have been added to the DOM and are in a specific order.
Also check out this answer I wrote up for a similar question.
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.
I have this chart, but as you can see it has some problems:
The tooltip height is wrong, there is that ugly blank space at the top. Since nvd3 has no documentation I really don't know how to proceed;
The x axis labels are all overlapping, I want either to remove them or to tilt them (like 45 deg.). The second option is best. I also tried .staggeredLabels(true) but they still overlap.
EDIT: I solved the second one by removing labels. Actually I don't remove them but rather hide them with:
.nv-x text {
display: none;
}
Since no one answered I just post the solution to the second problem:
.nv-x text {
display: none;
}
The blank spot is actually the key. It seems like maybe your object doesn't have a name?
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...