Skip to content

Commit 72b7e54

Browse files
lift elasticRadius to bubbleMixin
fixes #661
1 parent 88f5374 commit 72b7e54

5 files changed

+109
-54
lines changed

Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
## 2.1.2
2+
* Lift `elasticRadius` from `bubbleChart` to `bubbleMixin`, making it available to `bubbleOverlay` ([#661](https://github.com/dc-js/dc.js/issues/661))
23
Stop using `group.top()` in favor of `group.all()` sorting and slicing. ([#934](https://github.com/dc-js/dc.js/issues/934))
34
* Eliminate use of `group.top()` in cap mixin, by Macy Abbey ([#1184](https://github.com/dc-js/dc.js/pull/1184)). It already had to agree with `chart.ordering()` for the results to make sense.
45
* Eliminate `group.top()` in number display. This one is more problematic but probably less common. Although the number display now defaults ordering to `function (kv) { return kv.value; }`, applications which use a group with multiple bins with the number display, which were using `group.order()` to specify which bin should be displayed, must now specify `numberDisplay.ordering()` instead.

spec/bubble-overlay-spec.js

+81-31
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,39 @@ describe('dc.bubbleOverlay', function () {
33
var chart, data;
44
var dimension, group;
55

6-
describe('creation', function () {
7-
beforeEach(function () {
8-
data = crossfilter(loadDateFixture());
9-
dimension = data.dimension(function (d) {return d.state;});
10-
group = dimension.group().reduceSum(function (d) {return d.value;});
11-
12-
var id = 'bubble-overlay';
13-
var parent = appendChartID(id);
14-
var svg = parent.append('svg');
15-
16-
chart = dc.bubbleOverlay('#' + id)
17-
.svg(svg)
18-
.dimension(dimension)
19-
.group(group)
20-
.width(300)
21-
.height(200)
22-
.transitionDuration(0)
23-
.title(function (d) {return 'Title: ' + d.key;})
24-
.r(d3.scale.linear().domain([0, 500]))
25-
.ordinalColors(['blue'])
26-
.point('California', 100, 120)
27-
.point('Colorado', 300, 120)
28-
.point('Delaware', 500, 220)
29-
.point('Ontario', 180, 90)
30-
.point('Mississippi', 120, 220)
31-
.point('Oklahoma', 200, 350);
32-
33-
chart.render();
34-
});
6+
beforeEach(function () {
7+
data = crossfilter(loadDateFixture());
8+
dimension = data.dimension(function (d) {return d.state;});
9+
group = dimension.group().reduceSum(function (d) {return d.value;});
10+
11+
var id = 'bubble-overlay';
12+
var parent = appendChartID(id);
13+
var width = 600, height = 400;
14+
var svg = parent.append('svg')
15+
.attr({width: width, height: height});
16+
17+
chart = dc.bubbleOverlay('#' + id)
18+
.svg(svg)
19+
.dimension(dimension)
20+
.group(group)
21+
.width(width)
22+
.height(height)
23+
.transitionDuration(0)
24+
.title(function (d) {return 'Title: ' + d.key;})
25+
.r(d3.scale.linear().domain([0, 100]))
26+
.maxBubbleRelativeSize(0.1)
27+
.ordinalColors(['blue'])
28+
.point('California', 100, 120)
29+
.point('Colorado', 300, 120)
30+
.point('Delaware', 500, 220)
31+
.point('Ontario', 180, 90)
32+
.point('Mississippi', 120, 220)
33+
.point('Oklahoma', 200, 350);
34+
35+
chart.render();
36+
});
3537

38+
describe('creation', function () {
3639
it('should generate an instance of the dc chart', function () {
3740
expect(dc.instanceOfChart(chart)).toBeTruthy();
3841
});
@@ -60,8 +63,8 @@ describe('dc.bubbleOverlay', function () {
6063
});
6164

6265
it('should generate correct radii for circles', function () {
63-
expect(d3.select(chart.selectAll('circle.bubble')[0][0]).attr('r')).toEqual('34.64');
64-
expect(d3.select(chart.selectAll('circle.bubble')[0][3]).attr('r')).toEqual('22.32');
66+
expect(d3.select(chart.selectAll('circle.bubble')[0][0]).attr('r')).toEqual('87');
67+
expect(d3.select(chart.selectAll('circle.bubble')[0][3]).attr('r')).toEqual('48.5');
6568
});
6669

6770
it('should generate correct labels', function () {
@@ -98,5 +101,52 @@ describe('dc.bubbleOverlay', function () {
98101
expect(d3.select(chart.selectAll('g.node')[0][3]).attr('class')).toEqual('node ontario deselected');
99102
});
100103
});
104+
105+
function removeEmptyBins (group) {
106+
return {
107+
all: function () {
108+
return group.all().filter(function (d) {
109+
return d.value !== 0;
110+
});
111+
}
112+
};
113+
}
114+
describe('filtering another dimension', function () {
115+
var regionDim;
116+
beforeEach(function () {
117+
chart.group(removeEmptyBins(group)).render();
118+
regionDim = data.dimension(function (d) { return d.region; });
119+
});
120+
function expectRadii (expected) {
121+
var circles = chart.selectAll('circle.bubble')[0];
122+
console.log(circles.map(function (c) { return +d3.select(c).attr('r'); }));
123+
circles.forEach(function (c, i) {
124+
expect(+d3.select(c).attr('r')).toBeWithinDelta(expected[i], 0.1);
125+
});
126+
}
127+
describe('without elastic radius', function () {
128+
it('should have reasonable radii', function () {
129+
expectRadii([87, 21, 26.5, 48.5, 48.5, 37.5]);
130+
});
131+
it('filtering should zero out some radii', function () {
132+
regionDim.filter('Central');
133+
dc.redrawAll();
134+
expectRadii([0, 0, 0, 37.5, 48.5, 0]);
135+
});
136+
});
137+
describe('with elastic radius', function () {
138+
beforeEach(function () {
139+
chart.elasticRadius(true).render();
140+
});
141+
it('should lock to the minimum and maximum radius sizes', function () {
142+
expectRadii([60, 10, 14.1, 30.8, 30.8, 22.5]);
143+
});
144+
it('filtering should lock the remaining bubbles to min and max radius sizes', function () {
145+
regionDim.filter('Central');
146+
dc.redrawAll();
147+
expectRadii([0, 0, 0, 10, 60, 0]);
148+
});
149+
});
150+
});
101151
});
102152

src/bubble-chart.js

+1-23
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
dc.bubbleChart = function (parent, chartGroup) {
2929
var _chart = dc.bubbleMixin(dc.coordinateGridMixin({}));
3030

31-
var _elasticRadius = false;
32-
3331
_chart.transitionDuration(750);
3432

3533
_chart.transitionDelay(0);
@@ -38,28 +36,8 @@ dc.bubbleChart = function (parent, chartGroup) {
3836
return 'translate(' + (bubbleX(d)) + ',' + (bubbleY(d)) + ')';
3937
};
4038

41-
/**
42-
* Turn on or off the elastic bubble radius feature, or return the value of the flag. If this
43-
* feature is turned on, then bubble radii will be automatically rescaled to fit the chart better.
44-
* @method elasticRadius
45-
* @memberof dc.bubbleChart
46-
* @instance
47-
* @param {Boolean} [elasticRadius=false]
48-
* @returns {Boolean|dc.bubbleChart}
49-
*/
50-
_chart.elasticRadius = function (elasticRadius) {
51-
if (!arguments.length) {
52-
return _elasticRadius;
53-
}
54-
_elasticRadius = elasticRadius;
55-
return _chart;
56-
};
57-
5839
_chart.plotData = function () {
59-
if (_elasticRadius) {
60-
_chart.r().domain([_chart.rMin(), _chart.rMax()]);
61-
}
62-
40+
_chart.calculateRadiusDomain();
6341
_chart.r().range([_chart.MIN_RADIUS, _chart.xAxisLength() * _chart.maxBubbleRelativeSize()]);
6442

6543
var data = _chart.data();

src/bubble-mixin.js

+24
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ dc.bubbleMixin = function (_chart) {
1111
var _maxBubbleRelativeSize = 0.3;
1212
var _minRadiusWithLabel = 10;
1313
var _sortBubbleSize = false;
14+
var _elasticRadius = false;
1415

1516
_chart.BUBBLE_NODE_CLASS = 'node';
1617
_chart.BUBBLE_CLASS = 'bubble';
@@ -55,6 +56,29 @@ dc.bubbleMixin = function (_chart) {
5556
return _chart;
5657
};
5758

59+
/**
60+
* Turn on or off the elastic bubble radius feature, or return the value of the flag. If this
61+
* feature is turned on, then bubble radii will be automatically rescaled to fit the chart better.
62+
* @method elasticRadius
63+
* @memberof dc.bubbleChart
64+
* @instance
65+
* @param {Boolean} [elasticRadius=false]
66+
* @returns {Boolean|dc.bubbleChart}
67+
*/
68+
_chart.elasticRadius = function (elasticRadius) {
69+
if (!arguments.length) {
70+
return _elasticRadius;
71+
}
72+
_elasticRadius = elasticRadius;
73+
return _chart;
74+
};
75+
76+
_chart.calculateRadiusDomain = function () {
77+
if (_elasticRadius) {
78+
_chart.r().domain([_chart.rMin(), _chart.rMax()]);
79+
}
80+
};
81+
5882
/**
5983
* Get or set the radius value accessor function. If set, the radius value accessor function will
6084
* be used to retrieve a data value for each bubble. The data retrieved then will be mapped using

src/bubble-overlay.js

+2
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ dc.bubbleOverlay = function (parent, chartGroup) {
9696

9797
function initializeBubbles () {
9898
var data = mapData();
99+
_chart.calculateRadiusDomain();
99100

100101
_points.forEach(function (point) {
101102
var nodeG = getNodeG(point, data);
@@ -155,6 +156,7 @@ dc.bubbleOverlay = function (parent, chartGroup) {
155156

156157
function updateBubbles () {
157158
var data = mapData();
159+
_chart.calculateRadiusDomain();
158160

159161
_points.forEach(function (point) {
160162
var nodeG = getNodeG(point, data);

0 commit comments

Comments
 (0)