D3-tip tooltips are getting stuck after zoom-in in dc.js chart - d3.js

I have create a stacked bar chart having zoom & brush features with range selector sub-chart using dc.js.
There is tool-tip on the top chart which shows on mouse hover using d3-tip. After doing brush or zooming the tool-tips mostly gets stuck & does not get hide.
I am adding tool-tip using below code.
.on("pretransition",(c)=> {
this.addTooltip();//calling tool-tip method
})
And using below logic to show & hide the tool-tip on different events
this.mainChart.selectAll('rect').call(tip)
.on('mouseover', tip.show)
.on('mouseout', tip.hide)
.on('wheel',tip.hide)
.on('mousezoomin.zoom',tip.hide)
.on('mousezoomout.zoom',tip.hide)
.on('mousewheel.zoom', tip.hide)
.on('mouseup', tip.hide)
.on('mousewheel', tip.hide)
.on('mousezoomout', tip.hide)
.on('mousezoomin', tip.hide)
.on('mousemove', (d) => { //...});
Let me know how to solve tool-tip stuck issue after zooming or brushing of chart.
Thanks in advance.

Related

are there any way to change c3js stacked area chart opacity on mouse hover

I have a question regarding c3.js.
Currently, we are using c3js to display a stacked area chart, that is pretty fine, but our client asked us if we can change the individual area's opacity when customer is mouse hovering one area.
I could not find any solution for this, and hope to hear your suggetions.
Thanks
Try adding this after you've set up your chart -->
d3.selectAll(".c3-area")
.style ("pointer-events", "all")
.on("mouseover", function (d) { return d3.select(this).style("opacity", 0.6)})
.on("mouseout", function (d) { return d3.select(this).style("opacity", 0.2)})
;
The pointer-events setting is the important bit as by default most of the elements in the c3 chart are styled to ignore them.
Add it to the end of the c3 example to see it working --> https://c3js.org/samples/chart_area.html

d3 stacked area tooltip

I have this stacked area chart and I am trying to get the correct value, but have no real idea how.
I was trying to place a transparent rectangle over the chart, but then realized that I still have no idea, how to get the values.
.on("mousemove", function(d) {
tooltip
.style("display", "inline-block")
.html(d[0][1]);
})
This will give me only a fix value.
Here is my plunker
Maybe you guys have an idea.
If you inspect the data object (d), though it is array-like, you can see it also has key and index properties, and that should lead you to the right data.
.on("mousemove", function(d) {
tooltip
.style("display", "inline-block")
.html(d[d.index].data[d.key]);
})
The key is determined by the key accessor stack.keys(...) that you have defined in your plunker.
Also see the docs for the stack generator: https://github.com/d3/d3-shape/blob/master/README.md#stacks

Display the mouse over values from a pie chart outside the chart in dc.js [duplicate]

This question already has an answer here:
dc.js - display mouseover values from chart outside graph
(1 answer)
Closed 5 years ago.
I want to display the values that are currently displayed on top of the chart on mouseover, outside the chart instead.
I tried to dig further into the dc.js file, but couldn't figure out where the values are being displayed.
Can anyone suggest which function is being called internally inside dc.js?
Thanks for your response! It worked for me. My code mentioned below:
I added this span inside the section for Gender div:
Used mouse over event with renderlet event:
.on('renderlet', function(genderTypeChart) {
genderTypeChart.selectAll('g.pie-slice')
.on('mouseover', function(d) {
genderTypeChart.select('.display-gender').text(d.data.value);
})
.on('mouseout', function(d) {
genderTypeChart.select('.display-gender').text('');
});
});

How to apply tooltips for dc.js chart after chart is rendered

I have multiple row charts (crossfilter + dc) and I want to customize the tooltip using d3-tip.
So basically the relevant code is:
rowtip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) { return d.key + ": " + d.value; });
...my dc charts ...
... then at the bottom of my script tags ...
d3.selectAll('g.row').call(rowtip);
d3.selectAll('g.row').on('mouseover', rowtip.show);
The code seems work, but the mouseover event doesn't get triggered automatically and the tooltips don't get displayed when the page loads.
But If I run the last line (mouseover) on the console, then everything works as expected.
So my question would be how can I make sure the mouseover event gets triggered when the page loads. I tried Jquery $(document).ready(....), but that didn't work.
It has to have something to do with the order in which the elements are loaded... I guess. But I'm not an expert in javascript and much less in d3.
Thanks in advance.
Your way works fine but here is the idiomatic dc.js way to do it:
chart.on('pretransition.add-tip', function(chart) {
chart.selectAll('g.row')
.call(rowtip)
.on('mouseover', rowtip.show)
.on('mouseout', rowtip.hide);
});
The pretransition event fires after the chart is rendered or redrawn. add-tip is an event namespace to avoid interfering with anything else which may be watching this event.
chart.selectAll selects only items within the chart, to avoid accidental tooltips elsewhere in the page.
Here seems similar to your requirement, check it
http://bl.ocks.org/phil-pedruco/9032348
So I was able to solve this by using jquery after all. Seems a bit hacky, but it does what I need.
Basically I am forcing the call of the d3-tip function on mouseover of the html body.
var rowtip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d){return d.key;})
$('body').on('mouseover', function(){
d3.selectAll('g.row')
.call(rowtip)
.on('mouseover', rowtip.show)
.on('mouseout', rowtip.hide);
});

D3.js: Stop transitions interrupting on mouseover?

I'm working with D3's enter/exit selections, and I want to add a transition on mouseover events too.
The problem is that if I mouseover the letters as they are moving, they freeze, because the position transition is interrupted.
Here is a JSFiddle demonstrating the problem: http://jsfiddle.net/uEuE4/1/ and this is the code I'm using to add mouseover events to the update and enter selections:
text
.on('mouseover', function(d) {
d3.select(this).transition().duration(100).style('fill', 'yellow');
});
How can I only add the mouseover event handlers once all other transitions are completed, in order to stop the letters freezing?
Any tips for making the code more DRY would be very welcome too.
You can allocate a name to transition, then this transition will only be interrupted by new transition with the same name.
text
.on('mouseover', function(d) {
d3.select(this).transition("fillColor").duration(100).style('fill', 'yellow');
});
I upvoted and agree with #Jason answer, this will try to complete the previous with some clarifications and a simple demo that can be used as playground for multiple transition behaviour.
Inspecting your code you have various animations going on but only two of them need to be named to get rid of all your transitions "colisions",
the two event listeners:
text.on('mouseover', function(d) {
d3.select(this).transition("texTr").duration(100).style('fill', 'yellow');
});
enter_text.on('mouseover', function(d) {
d3.select(this).transition("enterTexTr").duration(100).style('fill', 'yellow');
});
The long story is that without names D3 thinks that all the transitions in your code are the same thus it stops the ongoing transition (an example can be a letter transitioning) and replaces it with a new one (for example a fill transition called by the event listener), because the transition name are the same.
But sometimes the desired behaviour is to explicitly stop transition on some elements; this can be done using .interrupt("transitionName"):
.on("mouseover", function() {
d3.select(this).interrupt("fadeOut")
.attr("fill", "orange")
})
.on("mouseout", function(d) {
d3.select(this).transition("fadeOut")
.duration(5000)
.attr("fill", "rgb(0, 0, " + (d * 10) + ")");
})
In this case without the interrupt command we can't trigger the fill orange until the fadeOut ends (5 seconds!).
Here the FIDDLE that you can play with :)
I also had a problem with mouseovers interrupting transitions, and came up with the following (admittedly hacky) solution: before the transition, add the css style pointer-events: none to the svg element; then remove it after the transition. Actually, I've found it works more reliably to apply the style to an element which encloses the svg.
E.g.:
<div class="chart-container">
<svg></svg>
</div>
Then:
$('.chart-container').addClass('no-mouse');
d3.select("svg").on("mouseover", function(d) {...})
.on("mouseout", function(d) {...})
.transition()
.duration(animDuration)
.attr("...", ...);
setTimeout(function() {
$('.chart-container').removeClass('no-mouse');
}, animDuration+10);
with the css:
.no-mouse {
pointer-events: none;
}
Works in Firefox, Safari, Chrome and even IE 8. But keen to hear a cleaner solution.

Resources