Skip to content

Commit 6e88ce5

Browse files
committed
Using d3.svg.axis instead of custom axis implementation on heatmap
1 parent 0af6292 commit 6e88ce5

File tree

4 files changed

+63
-64
lines changed

4 files changed

+63
-64
lines changed

spec/bubble-chart-spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ describe('dc.bubbleChart', function () {
691691
}
692692
describe('column filtering with straight crossfilter', function () {
693693
beforeEach(function () {
694-
var axisLabel = d3.select(heatMap.selectAll('.cols.axis text')[0][3]);
694+
var axisLabel = d3.select(heatMap.selectAll('.cols.axis g')[0][3]);
695695
axisLabel.on('click')(axisLabel.datum());
696696
d3.timer.flush();
697697
});
@@ -709,7 +709,7 @@ describe('dc.bubbleChart', function () {
709709
beforeEach(function () {
710710
chart.group(clone_group(sepalGroup));
711711
chart.render();
712-
var axisLabel = d3.select(heatMap.selectAll('.cols.axis text')[0][3]);
712+
var axisLabel = d3.select(heatMap.selectAll('.cols.axis g')[0][3]);
713713
axisLabel.on('click')(axisLabel.datum());
714714
d3.timer.flush();
715715
});

spec/heatmap-spec.js

+10-14
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,9 @@ describe('dc.heatmap', function () {
7676
});
7777

7878
it('should position the y-axis labels with their associated rows', function () {
79-
var yaxisTexts = chart.selectAll('.rows.axis text');
80-
expect(+yaxisTexts[0][0].getAttribute('y')).toEqual(150);
81-
expect(+yaxisTexts[0][0].getAttribute('x')).toEqual(0);
82-
expect(+yaxisTexts[0][1].getAttribute('y')).toEqual(50);
83-
expect(+yaxisTexts[0][1].getAttribute('x')).toEqual(0);
79+
var yaxisTicks = chart.selectAll('.rows.axis .tick');
80+
expect(yaxisTicks[0][0].getAttribute('transform')).toMatchTranslate(0, 150);
81+
expect(yaxisTicks[0][1].getAttribute('transform')).toMatchTranslate(0, 50);
8482
});
8583

8684
it('should have labels on the y-axis corresponding to the row values', function () {
@@ -90,11 +88,9 @@ describe('dc.heatmap', function () {
9088
});
9189

9290
it('should position the x-axis labels with their associated columns', function () {
93-
var xaxisTexts = chart.selectAll('.cols.axis text');
94-
expect(+xaxisTexts[0][0].getAttribute('y')).toEqual(200);
95-
expect(+xaxisTexts[0][0].getAttribute('x')).toEqual(50);
96-
expect(+xaxisTexts[0][1].getAttribute('y')).toEqual(200);
97-
expect(+xaxisTexts[0][1].getAttribute('x')).toEqual(150);
91+
var xaxisTexts = chart.selectAll('.cols.axis .tick');
92+
expect(xaxisTexts[0][0].getAttribute('transform')).toMatchTranslate(50, 0);
93+
expect(xaxisTexts[0][1].getAttribute('transform')).toMatchTranslate(150, 0);
9894
});
9995

10096
it('should have labels on the x-axis corresponding to the row values', function () {
@@ -355,13 +351,13 @@ describe('dc.heatmap', function () {
355351

356352
describe('with nothing previously filtered', function () {
357353
it('should filter all cells on that axis', function () {
358-
chart.selectAll('.cols.axis text').each(function (d) {
354+
chart.selectAll('.cols.axis g').each(function (d) {
359355
var axisLabel = d3.select(this);
360356
axisLabel.on('click')(d);
361357
assertOnlyThisAxisIsFiltered(chart, 0, d);
362358
axisLabel.on('click')(d);
363359
});
364-
chart.selectAll('.rows.axis text').each(function (d) {
360+
chart.selectAll('.rows.axis g').each(function (d) {
365361
var axisLabel = d3.select(this);
366362
axisLabel.on('click')(d);
367363
assertOnlyThisAxisIsFiltered(chart, 1, d);
@@ -380,7 +376,7 @@ describe('dc.heatmap', function () {
380376

381377
var xVal = box.datum().key[0];
382378

383-
var columns = chart.selectAll('.cols.axis text');
379+
var columns = chart.selectAll('.cols.axis g');
384380
var column = columns.filter(function (columnData) {
385381
return columnData === xVal;
386382
});
@@ -404,7 +400,7 @@ describe('dc.heatmap', function () {
404400

405401
assertOnlyThisAxisIsFiltered(chart, 0, xVal);
406402

407-
var columns = chart.selectAll('.cols.axis text');
403+
var columns = chart.selectAll('.cols.axis g');
408404
var column = columns.filter(function (columnData) {
409405
return columnData === xVal;
410406
});

src/heatmap.js

+42-45
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ dc.heatMap = function (parent, chartGroup) {
2929
var _rowOrdering = d3.ascending;
3030
var _colScale = d3.scale.ordinal();
3131
var _rowScale = d3.scale.ordinal();
32+
var _colAxis = d3.svg.axis().orient('bottom');
33+
var _rowAxis = d3.svg.axis().orient('left');
3234

3335
var _xBorderRadius = DEFAULT_BORDER_RADIUS;
3436
var _yBorderRadius = DEFAULT_BORDER_RADIUS;
@@ -185,6 +187,13 @@ dc.heatMap = function (parent, chartGroup) {
185187
.append('g')
186188
.attr('class', 'heatmap')
187189
.attr('transform', 'translate(' + _chart.margins().left + ',' + _chart.margins().top + ')');
190+
_chartBody.append('g')
191+
.attr('class', 'cols axis')
192+
.attr('transform', 'translate(0,' + _chart.effectiveHeight() + ')');
193+
_chartBody.append('g')
194+
.attr('class', 'rows axis');
195+
_colScale.rangeRoundBands([0, _chart.effectiveWidth()]);
196+
_rowScale.rangeRoundBands([_chart.effectiveHeight(), 0]);
188197

189198
return _chart._doRedraw();
190199
};
@@ -202,17 +211,39 @@ dc.heatMap = function (parent, chartGroup) {
202211
rows = _rowScale.domain(rows);
203212
cols = _colScale.domain(cols);
204213

205-
var rowCount = rows.domain().length,
206-
colCount = cols.domain().length,
207-
boxWidth = Math.floor(_chart.effectiveWidth() / colCount),
208-
boxHeight = Math.floor(_chart.effectiveHeight() / rowCount);
214+
// Update axis
215+
_colAxis.scale(cols)
216+
.tickFormat(_chart.colsLabel());
217+
var _colAxisTransition = dc.transition(_chartBody.select('g.cols.axis'), _chart.transitionDuration(), _chart.transitionDelay())
218+
.call(_colAxis);
219+
_rowAxis.scale(rows)
220+
.tickFormat(_chart.rowsLabel());
221+
var _rowAxisTransition = dc.transition(_chartBody.select('g.rows.axis'), _chart.transitionDuration(), _chart.transitionDelay())
222+
.call(_rowAxis);
223+
// We need the clicks added after the transition. Unfortunately, this is handled differently
224+
// for selection/transition
225+
if (_colAxisTransition.duration || _rowAxisTransition.duration) {
226+
_colAxisTransition.each('end', function () {
227+
d3.select(this)
228+
.selectAll('g')
229+
.on('click', _chart.xAxisOnClick());
230+
});
231+
_rowAxisTransition.each('end', function () {
232+
d3.select(this)
233+
.selectAll('g')
234+
.on('click', _chart.yAxisOnClick());
235+
});
236+
} else {
237+
_colAxisTransition.selectAll('g').on('click', _chart.xAxisOnClick());
238+
_rowAxisTransition.selectAll('g').on('click', _chart.yAxisOnClick());
239+
}
209240

210-
cols.rangeRoundBands([0, _chart.effectiveWidth()]);
211-
rows.rangeRoundBands([_chart.effectiveHeight(), 0]);
241+
// Update boxes
242+
var boxes = _chartBody.selectAll('g.box-group')
243+
.data(_chart.data(), function (d, i) {
244+
return _chart.keyAccessor()(d, i) + '\0' + _chart.valueAccessor()(d, i);
245+
});
212246

213-
var boxes = _chartBody.selectAll('g.box-group').data(_chart.data(), function (d, i) {
214-
return _chart.keyAccessor()(d, i) + '\0' + _chart.valueAccessor()(d, i);
215-
});
216247
var gEnter = boxes.enter().append('g')
217248
.attr('class', 'box-group');
218249

@@ -232,45 +263,11 @@ dc.heatMap = function (parent, chartGroup) {
232263
.attr('rx', _xBorderRadius)
233264
.attr('ry', _yBorderRadius)
234265
.attr('fill', _chart.getColor)
235-
.attr('width', boxWidth)
236-
.attr('height', boxHeight);
266+
.attr('width', _colScale.rangeBand())
267+
.attr('height', _rowScale.rangeBand());
237268

238269
boxes.exit().remove();
239270

240-
var gCols = _chartBody.select('g.cols');
241-
if (gCols.empty()) {
242-
gCols = _chartBody.append('g').attr('class', 'cols axis');
243-
}
244-
var gColsText = gCols.selectAll('text').data(cols.domain());
245-
gColsText.enter().append('text')
246-
.attr('x', function (d) { return cols(d) + boxWidth / 2; })
247-
.style('text-anchor', 'middle')
248-
.attr('y', _chart.effectiveHeight())
249-
.attr('dy', 12)
250-
.on('click', _chart.xAxisOnClick())
251-
.text(_chart.colsLabel());
252-
dc.transition(gColsText, _chart.transitionDuration(), _chart.transitionDelay())
253-
.text(_chart.colsLabel())
254-
.attr('x', function (d) { return cols(d) + boxWidth / 2; })
255-
.attr('y', _chart.effectiveHeight());
256-
gColsText.exit().remove();
257-
var gRows = _chartBody.select('g.rows');
258-
if (gRows.empty()) {
259-
gRows = _chartBody.append('g').attr('class', 'rows axis');
260-
}
261-
var gRowsText = gRows.selectAll('text').data(rows.domain());
262-
gRowsText.enter().append('text')
263-
.attr('dy', 6)
264-
.style('text-anchor', 'end')
265-
.attr('x', 0)
266-
.attr('dx', -2)
267-
.on('click', _chart.yAxisOnClick())
268-
.text(_chart.rowsLabel());
269-
dc.transition(gRowsText, _chart.transitionDuration(), _chart.transitionDelay())
270-
.text(_chart.rowsLabel())
271-
.attr('y', function (d) { return rows(d) + boxHeight / 2; });
272-
gRowsText.exit().remove();
273-
274271
if (_chart.hasFilter()) {
275272
_chart.selectAll('g.box-group').each(function (d) {
276273
if (_chart.isSelectedNode(d)) {

style/dc.scss

+9-3
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,15 @@ div.dc-chart {
232232
fill-opacity: 0.5;
233233
fill: $color_celeste;
234234
}
235-
g.axis text {
236-
pointer-events: all;
237-
cursor: pointer;
235+
g.axis {
236+
text {
237+
pointer-events: all;
238+
cursor: pointer;
239+
}
240+
.domain,
241+
.tick line {
242+
opacity: 0;
243+
}
238244
}
239245
}
240246
.empty-chart .pie-slice {

0 commit comments

Comments
 (0)