I have a bar chart with multiple Y-Axis as you can see in the image below.
As you can see the two bar represents two different datasets. The onclick event of the canvas provides us an array of all the bar points.
canvas.onclick = function (evt) {
var activePoints = chartObject.getBarsAtEvent(evt);
}
Now the problem is that in our application we have do two different thing based on which bar the user clicks on. Using the above points we are not able to determine which bar the user clicked on, meaning if the user clicks on blue bar then we need to do something or else if the user clicks on purple bar then we do something completely different. How can we determine which bar the user clicked.
Unfortunately, there is no support for that, you have to implement it by yourself.
See https://github.com/chartjs/Chart.js/issues/3115#event-792845174
See also this solution: https://github.com/chartjs/Chart.js/issues/1283
Related
I just need to know how to disable a single legend item programmatically on chart reload (disable means: legend is shown greyed out and its linked curve is hidden), as I need to reload a chart with some new data using some back and forward arrows, but still need to remember the user preference or the state of legend items (on/off)
You can just call hide on the series associated with that legend marker to hide the series/grey out the marker:
series.hide();
Thanks #xorspark that's really it, it's about controlling the series not legend.
It happened to work specifically with the appeared or inited events, not shown event as it seemed to be, like this:
series.events.on("inited", () => {
reactState ? series.show() : series.hide();
});
inited event even works better, as disabled legends will not show a glimpse of their color on the curve when using appeared.
I'm trying to create a data visualization in d3.js that contains two charts: a parallel-axis plot, and horizontal colorbar chart (I just made up that name, but it's basically a series of colored rectangles). Each line in the parallel-axis plot is associated with a set of rectangles in the colorbar chart.
Right now, mousing over a given line highlights that line, and mousing over a given rectangle highlights that set of rectangles. My goal is to also highlight the associated line or set of rectangles on the opposite chart anytime the user mouses over either chart. This seems like it would be pretty straightforward if I generated both charts with the same function. However, it would be much neater (and more reusable) coding style to give each chart its own function and just connect them somehow. I tried having each within-chart mouseover function call a function defined at a higher level that affected both charts, but this didn't seem to have any effect on the chart that wasn't moused-over. Since I still don't feel like I fully understand how d3.js works on an underlying level, I'd really like to have confirmation that this is a viable way to set up my code. My code is long and complicated, and I really just want advice on the structure, so here is the basic outline:
function chart1(){
make chart
function mouseover(d,i){
do stuff
chart1_globalmouseover(d,i);
}
chartElement.on("mouseover", function(d,i){mouseover(d,i)});
}
function chart2(){
make chart
function mouseover(d,i){
do stuff
chart2_globalmouseover(d,i);
}
chartElement.on("mouseover", function(d,i){mouseover(d,i)});
}
function chart1_globalmouseover(d,i){
do stuff in chart 2's mouseover function
}
function chart2_globalmouseover(d,i){
do stuff in chart 1's mouseover function
}
c1 = chart1();
c2 = chart2();
One way to link the two graphs independent of the code used to create them would be to assign IDs or classes to the elements you may want to select. That is, if graph 2 has an element with ID foo, then in a mouse handler for an element of graph 1, you could say d3.select("#foo").style("stroke", "red") for example. Similarly with classes.
This approach allows you to keep the code completely separate. Moreover, if you use classes, you can assign the same class to things you would want to highlight together (e.g. elements representing the same data). Then d3.selectAll(".class") would select and allow you to manipulate all of them. This would work for an arbitrary number of graphs, not just two -- what changes is simply the number of elements that will be selected.
I made a chart using Google Visualization's ColumnChart like this.
It's basically a stacked column chart using 3 x 7 matrix. In every bar, I remove the data for two other rows.
My problem is how to make the yellow bar (or other bar) looks like it has been clicked from the start using the Javascript code. Just like below.
*Notice the light border in the yellow bar.
You can programmatically select a bar by calling setSelection() on the chart. This can only be done after the "ready" event has been fired, i.e. you can set the selection upon this event being triggered as follows:
google.visualization.events.addListener(chart, 'ready', readyHandler);
function readyHandler(e) {
chart.setSelection([{"row":1,"column":1}]);
}
Here's a working example where we programmatically select the second bar after the chart has been drawn: http://jsfiddle.net/FFEZT/
I have following combined stacked bar with 2 data series: blue and red one. The red one is a single point (of line) and it is by default "invisible" (cover with blue data), you can hover over it, its Y coordinate is about 54 +1 for each day after this question is asked :)
Now the question is, how to make the red dot visible? If I select it, it remains on top, that is exactly what I want by default. Any ideas?
Thanks
I'm gonna answer my question, but it is just workaround (working though). After chart is ready, I'm listening to the 'ready' event and immediately select the single point like this
google.visualization.events.addListener(chart, 'ready', function() {
ac.setSelection([{row:0, column:5}]); // use proper values
});
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