Browse Source

Add Exploded pie. Add config.pie_explodeRadius and

chart.pie.explodeRadius() API. Closes #1754
pull/1756/head
missingdays 9 years ago
parent
commit
7ec6384e4d
  1. 1
      Gruntfile.coffee
  2. 34
      spec/api.pie-spec.js
  3. 126
      spec/arc-spec.js
  4. 12
      src/api.pie.js
  5. 38
      src/arc.js
  6. 1
      src/config.js

1
Gruntfile.coffee

@ -72,6 +72,7 @@ module.exports = (grunt) ->
'src/api.legend.js',
'src/api.chart.js',
'src/api.tooltip.js',
'src/api.pie.js',
'src/c3.axis.js',
'src/ua.js',
'src/polyfill.js',

34
spec/api.pie-spec.js

@ -0,0 +1,34 @@
describe('c3 api pie', function () {
'use strict';
var chart;
var args = {
data: {
columns: [
['data1', 30],
['data2', 1000],
['data3', 5000]
]
},
type: 'pie',
pie: {
explodeRadius: 10
}
};
beforeEach(function (done) {
chart = window.initChart(chart, args, done);
});
describe('explodeRadius', function(){
it('should get explode radius', function(){
expect(chart.pie.explodeRadius()).toBe(10);
});
it('should set explode radius', function(){
chart.pie.explodeRadius(20);
expect(chart.pie.explodeRadius()).toBe(20);
});
});
});

126
spec/arc-spec.js

@ -156,4 +156,130 @@ describe('c3 chart arc', function () {
});
});
describe('explodeRadius', function(){
it('should set args with explodeRadius', function(){
args = {
data: {
columns: [
['data1', null],
['data2', null],
['data3', null]
],
type: 'pie'
},
pie:{
explodeRadius: 10
}
};
expect(true).toBeTruthy();
});
it('should have correct d attribute', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = {
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1')
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2')
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3')
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
};
expect(arcs.data1.attr('d').indexOf('NaN')).toBe(-1);
expect(arcs.data2.attr('d').indexOf('NaN')).toBe(-1);
expect(arcs.data3.attr('d').indexOf('NaN')).toBe(-1);
});
it('should have the usual behaviout with explodeRadius set to 0', function () {
args = {
data: {
columns: [
['data1', 30],
['data2', 150],
['data3', 120]
],
type: 'pie'
},
pie: {
explodeRadius: 0
}
};
expect(true).toBeTruthy();
});
it('should have correct classes', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = {
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1')
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2')
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3')
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
};
expect(arcs.data1.size()).toBe(1);
expect(arcs.data2.size()).toBe(1);
expect(arcs.data3.size()).toBe(1);
});
it('should have correct d', function () {
expect(d3.select('.c3-arc-data1').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/);
expect(d3.select('.c3-arc-data2').attr('d')).toMatch(/M1\..+,-211\..+A211\..+,211\..+ 0 0,1 1\..+,211\..+L0,0Z/);
expect(d3.select('.c3-arc-data3').attr('d')).toMatch(/M1\..+,211\..+A211\..+,211\..+ 0 0,1 -124\..+,-171\..+L0,0Z/);
});
it('should set args with data id that can be converted to a color', function () {
args.data.columns = [
['black', 30],
['data2', 150],
['data3', 120]
];
expect(true).toBeTruthy();
});
it('should have correct d even if data id can be converted to a color', function (done) {
setTimeout(function () {
expect(d3.select('.c3-arc-black').attr('d')).toMatch(/M-124\..+,-171\..+A211\..+,211\..+ 0 0,1 -3\..+,-211\..+L0,0Z/);
done();
}, 500);
});
it('should update args to have empty pie chart', function () {
args = {
data: {
columns: [
['data1', null],
['data2', null],
['data3', null]
],
type: 'pie'
}
};
expect(true).toBeTruthy();
});
it('should have correct d attribute', function () {
var chartArc = d3.select('.c3-chart-arcs'),
arcs = {
data1: chartArc.select('.c3-chart-arc.c3-target.c3-target-data1')
.select('g.c3-shapes.c3-shapes-data1.c3-arcs.c3-arcs-data1')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data1'),
data2: chartArc.select('.c3-chart-arc.c3-target.c3-target-data2')
.select('g.c3-shapes.c3-shapes-data2.c3-arcs.c3-arcs-data2')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data2'),
data3: chartArc.select('.c3-chart-arc.c3-target.c3-target-data3')
.select('g.c3-shapes.c3-shapes-data3.c3-arcs.c3-arcs-data3')
.select('path.c3-shape.c3-shape.c3-arc.c3-arc-data3')
};
expect(arcs.data1.attr('d').indexOf('NaN')).toBe(-1);
expect(arcs.data2.attr('d').indexOf('NaN')).toBe(-1);
expect(arcs.data3.attr('d').indexOf('NaN')).toBe(-1);
});
});
});

12
src/api.pie.js

@ -0,0 +1,12 @@
c3_chart_fn.pie = function (){};
c3_chart_fn.pie.explodeRadius = function (radius) {
var $$ = this.internal, config = $$.config
if(radius === undefined){
return config.pie_explodeRadius;
}
config.pie_explodeRadius = radius;
this.flush();
};

38
src/arc.js

@ -13,6 +13,11 @@ c3_chart_internal_fn.updateRadius = function () {
w = config.gauge_width || config.donut_width;
$$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2;
$$.radius = $$.radiusExpanded * 0.95;
// Because we are exploding pie
// outer radius might become bigger that it should be
$$.radius -= config.pie_explodeRadius;
$$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : 0.6;
$$.innerRadius = $$.hasType('donut') || $$.hasType('gauge') ? $$.radius * $$.innerRadiusRatio : 0;
};
@ -289,7 +294,7 @@ c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransf
this._current = d;
});
mainArc
.attr("transform", function (d) { return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : ""; })
.attr("transform", $$.wrapExplode())
.style("opacity", function (d) { return d === this._current ? 0 : 1; })
.on('mouseover', config.interaction_enabled ? function (d) {
var updated, arcData;
@ -367,7 +372,7 @@ c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransf
return $$.getArc(interpolated, true);
};
})
.attr("transform", withTransform ? "scale(1)" : "")
.attr("transform", $$.wrapExplode())
.style("fill", function (d) {
return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id);
}) // Where gauge reading color would receive customization.
@ -412,6 +417,35 @@ c3_chart_internal_fn.redrawArc = function (duration, durationForExit, withTransf
.text(config.gauge_label_show ? config.gauge_max : '');
}
};
// This is needed because d3 binds transform function to DOM element,
// thus we can't just pass c3_chart_internal_fn.explode
// but need to close it against c3_chart_internal_fn
c3_chart_internal_fn.wrapExplode = function(){
var $$ = this, config = $$.config;
return function explode(d) {
d = $$.updateAngle(d);
if(d === null){
return "";
}
var offset = config.pie_explodeRadius;
if(offset <= 0){
return "translate(0, 0)";
}
var angle = (d.startAngle + d.endAngle) / 2;
var xOff = Math.sin(angle) * offset;
var yOff = -Math.cos(angle) * offset;
return 'translate(' + xOff + ',' + yOff +')';
};
};
c3_chart_internal_fn.initGauge = function () {
var arcs = this.arcs;
if (this.hasType('gauge')) {

1
src/config.js

@ -177,6 +177,7 @@ c3_chart_internal_fn.getDefaultConfig = function () {
pie_label_ratio: undefined,
pie_expand: {},
pie_expand_duration: 50,
pie_explodeRadius: 0,
// gauge
gauge_fullCircle: false,
gauge_label_show: true,

Loading…
Cancel
Save