Reputation: 173
I would like to display the value of heatMap boxes inside the boxes not just in the tool tip.
Looks although this feature has yet to be added according to: https://github.com/dc-js/dc.js/issues/1303 , would this be able to be accomplished with d3.js? Thanks.
HeatMap:
heatMap
.width(1000)
.height(400)
.dimension(dimension)
.group(filtered_heatMap_group)
.margins({
left: 200,
top: 30,
right: 10,
bottom: 50
})
.keyAccessor(function (d) {
return d.key[0];
})
.valueAccessor(function (d) {
return d.key[1];
})
.colorAccessor(function (d) {
return +d.value.color;
})
.title(function (d) {
return "Manager: " + d.key[1] + "\n" +
"FTE: " + d.value.toolTip + "\n" +
"Date: " + d.key[0] + "";
})
.rowOrdering(d3.descending);
https://jsfiddle.net/_M_M_/jvf5ot3p/3/
Upvotes: 5
Views: 925
Reputation: 20120
The devil is in the details.
It's pretty easy to get some text onto the boxes. Getting them nicely positioned and formatted will take some more work. I'll try to get you started anyway.
You can use the renderlet
event. pretransition
would be nicer, but we will need to steal some attributes from the rect
s because the chart's scales are not accessible, and these attributes aren't all initialized at pretransition
time.
This is a common pattern for annotations in dc.js: wait for a chart event, then select existing elements and add stuff to them. The element selectors are documented here; we want g.box-group
.
The rest is standard D3 general update pattern, except that as I mentioned, we don't have access to the scales. Rather than trying to duplicate that language and possibly getting it wrong, we can read attributes like x
, y
, width
, height
from the rect
s that already reside in these g
s.
SVG doesn't have multiline text, so we have to create tspan elements inside of text elements.
Putting that all together:
.on('renderlet.label', function(chart) {
var text = chart.selectAll('g.box-group')
.selectAll('text.annotate').data(d => [d]);
text.exit().remove();
// enter attributes => anything that won't change
var textEnter = text.enter()
.append('text')
.attr('class', 'annotate')
textEnter.selectAll('tspan')
.data(d => [d.key[1], d.value.toolTip, d.key[0]])
.enter().append('tspan')
.attr('text-anchor', 'middle')
.attr('dy', 10);
text = textEnter.merge(text);
// update attributes => position and text
text
.attr('y', function() {
var rect = d3.select(this.parentNode).select('rect');
return +rect.attr('y') + rect.attr('height')/2 - 15;
});
text.selectAll('tspan')
.attr('x', function() {
var rect = d3.select(this.parentNode.parentNode).select('rect');
return +rect.attr('x') + rect.attr('width')/2;
})
.text(d => d);
})
Notice that I gave up and nudged the text 15px up... there may or may not be a better way to get vertical centering of multiline text.
The text doesn't quite fit, even without descriptions. I'll let you figure that out.
But it's there and it updates correctly:
Upvotes: 2