I currently have a chart with 2 viewing options (regular data and percentages).
I also have a tooltip that shows the results for each line that I'm showing
When I switch options I want my tooltip to keep showing the info (the lines are getting drawn correctly) but instead what I'm seeing is that I'm creating several tooltip boxes for each time I switch options.
My tooltip is an append('g') to my main chart and I'm appending my tooltip box to this tooltip which is appended to my chart which is chartContent
Here's the tooltip box
const tooltipContainer = d3.select(".stackedChart").append("div")
.attr("class", css.divBox)
.style("opacity", 0);
tooltip.append("tooltipContainer")
On update (aka when switching options) I'm already doing this
chartContent.remove()
chartContent = chart.append('g') (to get the new info)
Now for my .divBox I was trying d3.selectAll(".divBox").remove(); but I can't seem to get it to work.
Every time I switch options I get one more .divBoxand I can see the bottom one updating with the info but the one following the tooltip is the top one (I think, I might be wrong).
What are my steps from here? I'm extremely confused
Related
I am using a c3 chart. I have a button to download it using canvg. I also have it toggle bars when legends are clicked. The download works and so do the toggles.
The only issue in the downloads is that I can either always show the legends (even if the bars they correspond to aren't being shown) or as soon as I toggle a legend the legend never appears again in the downloads (although it does on the chart itself).
What I would like is for the legends to only appear if their corresponding bars are actually being shown. I also don't want the legends to be hidden if their bar is being shown. (Legend Shown <=> Bar Shown kind of relationship)
I had issues with IE in the past so following https://github.com/c3js/c3/issues/2528 the display is 'Block'.
var string = ".c3-legend-item-hidden";//hides legends that are unselected in the download. Will KEEP them hidden even if retoggled :(
d3.selectAll(string).each(function() {
var element = this;
var computedStyle = getComputedStyle(element, null);
for (var i = 0; i < computedStyle.length; i++) {
var property = computedStyle.item(i);
element.style[property] = computedStyle.getPropertyValue(property);
}
});
//removing this section makes all legends appear permanently regardless of whether the bar does
Expected: a graph that has the correct bars and legends shown in the downloads
Actual:
(with code segment) hidden legends that do not reappear when needed
(without code segment) legends that are never hidden
Update: Just to clarify, this works when converting the graph to a downloaded svg file (adding xmlns etc.), just not when using canvg and downloading to a png file (which is what I need it to do).
Instead of using the computed style, manually set the styles you need.
This solution worked for me ('hidden' legends are slightly visible but it is now identical to my actual chart which is all I personally needed):
var string = ".c3-legend-item-hidden";
d3.selectAll(string).each(function() {
//this.style['visibility']='hidden'; // uncomment this out and it will completely hide the legend if that is what you want
this.style['opacity']= 0.15;
// set opacity as 0 to make the legend transparent to the point you can't see it (if that is what you want)
// or 0.15 to make it like the chart (as done here and in c3.css)
});
The computed styles give a lot more styles than you need and can override the styles you want.
I am trying to build a D3 bar chart visualization that can be updated using a drop down menu.
So far, I have successfully created the bar chart and the drop down menu such that when I change the selection in the menu, the bars are updated to their new values.
However, I am having problems with the bar labels updating appropriately. Even though I include the same .exit.remove() function for the labels as for the bars, the old labels remain on the newly updated chart.
Image of the updated chart w/ problem labels
Test csv file
Test code
Apologies for the links. I'm new to JSFiddle, and I couldn't figure out how to easily transfer my example.
You forgot to add class attribute while appending the text
You also need to change the text while updating
Hope this helps
bartexts.transition().duration(250)
.attr("y", function(d, i) {return yScale(d) - 10})
.text(function(d) {return d});
I'm looking for some advice on how to get two elements in a visualization, which are linked by a common data value, to respond simultaneously.
Here is the visualization as it stands now.
http://bl.ocks.org/natemiller/2686e5c0d9a1a4bb0895
Note that the different colored points are for the 50 US states in 2005 (green) and 2013 (blue), so there is a blue point and a green point for each state. I have two things I would like to get working here.
I would like to be able to mouseover either a blue point or a green point and have the corresponding point (for the same state) highlighted.
I would like a tooltip with some basic data to appear next to both points, providing point specific data.
Regarding the first point above. Right now when you mouseover a blue point the corresponding green point is highlighted, however, when you mouseover a green point only that point is highlighted and not its corresponding blue point. I imagine this is a simple fix, but for the life of me I can't figure out to reverse the reference so I get green to blue references as well.
Regarding the second point. Right now a tooltip with relevant information appears near the moused-over point, but I would like to have a similar tooltip appear next to the corresponding point from the alternate year of data, so that direct comparisons across years are easier. I am quite new to adding HTML tooltips so I'm not clear on how to do this and suspect it may require a new method for adding tooltips. Can any help to steer me in the correct direction for how to have a tooltip appear near the moused-over element and a corresponding linked element?
1) Remember that ids are unique and you're creating multiple circles with the same id, use a class instead
circles.attr("class", function(d) { return d.state })
2) You're creating a single tooltip, if you want to show one for each pair of states create multiple tooltips
Assuming that you make these changes you can easily create multiple tooltips for each pair of states
circles.on('mouseover', function (d) {
// selection for 2 states
var states = d3.selectAll('circle.' + d.state)
// code to style those nodes goes here ...
// tooltips for the states
var tooltips = d3.select('svg').selectAll('text.tooltip')
.data(states.data())
// initial styling of the tooltips goes here...
tooltips
.enter()
.append('text')
.attr('class', 'tooltip')
// update
tooltips
.html(function (d) {
// text of the tooltip
return 'something'
})
// positioning, it requires some margin fixes I guess
.attr('x', function (d) { return xScale(d.child_pov) })
.attr('y', function (d) { return yScale(d.non_math_prof) })
})
Finally remove the tooltips created on mouseover when the mouseout event is triggered
circles.on('mouseout', function (d) {
d3.select('svg').selectAll('text.tooltip').remove()
})
You cannot have multiple elements with the same id. Use a class .circleHawaii instead of an id #circleHawaii.
I'm trying to build some charts using AmCharts, and I need to set the titles dynamically. According to the docs, each chart should have an addTitle() method:
http://docs.amcharts.com/3/javascriptcharts/AmChart
addTitle(text, size, color, alpha, bold)
text - text of a title size - font size color - title color alpha - title opacity bold - boolean value indicating if title should be bold.
Adds title to the top of the chart. Pie, Radar positions are updated so that they won't overlap. Plot area of Serial/XY chart is also updated unless autoMargins property is set to false. You can add any number of titles - each of them will be placed in a new line. To remove titles, simply clear titles array: chart.titles = []; and call chart.validateNow() method.
I can see no such method. I'm creating the chart using AmCharts.makeChart(), passing a div and a chart definition object:
var chart = AmCharts.makeChart($chartDiv[0], chartDefinition);
When I examine my chart object, I can see the array of titles I've included in my chartDefinition, but there's no addTitle() method defined on it.
As i have to rights to comment atm, i'm posting this as answer.
I made a JSFiddle and tried to reproduce your problem. As you can see everything is working fine. (Even with only one parameter in addTitle)Maybe you could post your code, if your problem is still occuring?
I'm using D3 to display multiple bar charts (30+ charts) similar to the example here: http://phrogz.net/js/d3-playground/#MultiBars_HTML As the user hovers over a bar I want to change the title of just the chart the user is interacting with, with information about the value the user is hovering over.
So if I add something like:
bars.on('mouseover', mouseoverfunc);
function mouseoverfunc(d, i) {
// update the title just for this chart..not all charts
a.select("h2").text(function (d) { return "hello"; });
}
So knowing the mouseover is on the bar [d3.select(this)], how do I select the parent so I can change just the title of one chart? There is a very similar example here: http://mbostock.github.com/protovis/ex/minnesota.html that I'm trying to replicate in D3
Thanks.
The easiest way is probably to assign an attribute to your title divs that let you find them with a select statement, something like:
d3.select("[parentBarChartID="+d.id+"]")
in your mouseoverfunc.
Alternatively, you couldmake your DOM elements hierarchical such that you can traverse using this.parentNode.childNodes, looping over all children until you find the title node (see how to loop over child nodes here.
I believe that the following two examples should show you how to individually select any bar and trigger a callback that selects any specific item...
"Multiple D3 Horizontal Bar Charts Mixed In With HTML Layout Constructs"
"Multiple D3 Vertical Bar Charts Mixed In With HTML Layout Constructs"
You'll notice in the callback functions "synchronizedMouseOver" and "synchronizedMouseOut" that they trigger the change of multiple objects on the SVG canvas... An individual bar, a legend bullet, and a legend text string. You would use the same methodology to change a chart title.
I hope this helps.
Frank