diff --git a/src/scripts/charts/pie.js b/src/scripts/charts/pie.js index ca7caf4..01cdde8 100644 --- a/src/scripts/charts/pie.js +++ b/src/scripts/charts/pie.js @@ -158,13 +158,17 @@ ].join(' ')); var endAngle = startAngle + dataArray[i] / totalDataSum * 360; + + // Use slight offset so there are no transparent hairline issues + var overlappigStartAngle = Math.max(0, startAngle - (i === 0 || hasSingleValInSeries ? 0 : 0.2)); + // If we need to draw the arc for all 360 degrees we need to add a hack where we close the circle // with Z and use 359.99 degrees - if(endAngle - startAngle === 360) { - endAngle -= 0.01; + if(endAngle - overlappigStartAngle >= 359.99) { + endAngle = overlappigStartAngle + 359.99; } - var start = Chartist.polarToCartesian(center.x, center.y, radius, startAngle), + var start = Chartist.polarToCartesian(center.x, center.y, radius, overlappigStartAngle), end = Chartist.polarToCartesian(center.x, center.y, radius, endAngle); // Create a new path element for the pie chart. If this isn't a donut chart we should close the path for a correct stroke @@ -239,7 +243,7 @@ } } - // Set next startAngle to current endAngle. Use slight offset so there are no transparent hairline issues + // Set next startAngle to current endAngle. // (except for last slice) startAngle = endAngle; } diff --git a/test/spec/spec-pie-chart.js b/test/spec/spec-pie-chart.js index 7df928b..7da5041 100644 --- a/test/spec/spec-pie-chart.js +++ b/test/spec/spec-pie-chart.js @@ -37,12 +37,14 @@ describe('Pie chart tests', function() { describe('Simple Pie Chart', function() { // https://gionkunz.github.io/chartist-js/examples.html#simple-pie-chart - function onCreated(callback) { - jasmine.getFixtures().set('
'); - var data = { + var num = '\\d+(\\.\\d*)?'; + var data, options; + + beforeEach(function() { + data = { series: [5, 3, 4] }; - var options = { + options = { width: 100, height: 100, chartPadding: 10, @@ -50,9 +52,11 @@ describe('Pie chart tests', function() { return Math.round(value / data.series.reduce(sum) * 100) + '%'; } }; - var sum = function(a, b) { return a + b; }; - + }); + + function onCreated(callback) { + jasmine.getFixtures().set(''); var chart = new Chartist.Pie('.ct-chart', data, options); chart.on('created', callback); } @@ -77,8 +81,6 @@ describe('Pie chart tests', function() { it('should create slice path', function(done) { onCreated(function() { $('.ct-slice-pie').each(function() { - - var num = '\\d+(\\.\\d*)?'; var pattern = '^M' + num + ',' + num + 'A40,40,0,0,0,' + num + ',' + num + @@ -99,36 +101,120 @@ describe('Pie chart tests', function() { done(); }); }); + + it('should overlap slices', function(done) { + data = { + series: [1, 1] + }; + onCreated(function() { + var slice1 = $('.ct-slice-pie').eq(0); + var slice2 = $('.ct-slice-pie').eq(1); + + expect(slice1.attr('d')).toMatch(/^M50,10A40,40,0,0,0,50.\d+,90L50,50Z/); + expect(slice2.attr('d')).toMatch(/^M50,90A40,40,0,0,0,50,10L50,50Z/); + done(); + }); + }); + + it('should set large arc sweep flag', function(done) { + data = { + series: [1, 2] + }; + onCreated(function() { + var slice1 = $('.ct-slice-pie').eq(0); + expect(slice1.attr('d')).toMatch(/^M50,10A40,40,0,1,0/); + done(); + }, data); + }); + + it('should draw complete circle with gap', function(done) { + data = { + series: [1] + }; + onCreated(function() { + var slice1 = $('.ct-slice-pie').eq(0); + expect(slice1.attr('d')).toMatch(/^M49.9\d+,10A40,40,0,1,0,50,10L50,50Z/); + done(); + }); + }); + + it('should draw complete circle with startAngle', function(done) { + data.series = [100]; + options.startAngle = 90; + onCreated(function() { + var slice1 = $('.ct-slice-pie').eq(0); + expect(slice1.attr('d')).toMatch(/^M90,49.9\d+A40,40,0,1,0,90,50L50,50Z/); + done(); + }); + }); + + it('should draw complete circle if values are 0', function(done) { + data = { + series: [0, 1, 0] + }; + onCreated(function() { + var slice1 = $('.ct-slice-pie').eq(1); + expect(slice1.attr('d')).toMatch(/^M49.9\d+,10A40,40,0,1,0,50,10L50,50Z/); + done(); + }); + }); }); - describe('Pie with small ratio', function() { - - function onCreated(callback) { - jasmine.getFixtures().set(''); - var data = { + describe('Pie with small slices', function() { + var data, options; + + beforeEach(function() { + data = { series: [0.001, 2] }; - var options = { + options = { width: 100, height: 100, chartPadding: 0, - }; + }; + }); + + function onCreated(callback) { + jasmine.getFixtures().set(''); var chart = new Chartist.Pie('.ct-chart', data, options); chart.on('created', callback); } - - it('should render correctly with very small slices', function(done) { - onCreated(function() { + it('Pie should render correctly with very small slices', function(done) { + onCreated(function() { var slice1 = $('.ct-slice-pie').eq(0); - var slice2 = $('.ct-slice-pie').eq(1); + var slice2 = $('.ct-slice-pie').eq(1); - expect(slice1.attr('d')).toMatch(/^M50,0A50,50,0,1,0,50.1\d+,0/); + expect(slice1.attr('d')).toMatch(/^M49.9\d*,0A50,50,0,1,0,50,0/); expect(slice2.attr('d')).toMatch(/^M50.1\d+,0A50,50,0,0,0,50,0/); done(); }); }); + + it('Pie should render correctly with very small slices on startAngle', function(done) { + options.startAngle = 90; + onCreated(function() { + var slice1 = $('.ct-slice-pie').eq(0); + var slice2 = $('.ct-slice-pie').eq(1); + + expect(slice1.attr('d')).toMatch(/^M100,49.97\d*A50,50,0,1,0,100,49.98\d*/); + expect(slice2.attr('d')).toMatch(/^M100,50.1\d*A50,50,0,0,0,100,50/); + done(); + }); + }); + + it('Donut should render correctly with very small slices', function(done) { + options.donut = true; + onCreated(function() { + var slice1 = $('.ct-slice-donut').eq(0); + var slice2 = $('.ct-slice-donut').eq(1); + + expect(slice1.attr('d')).toMatch(/^M49.9\d*,30A20,20,0,1,0,50,30/); + expect(slice2.attr('d')).toMatch(/^M50.\d+,30A20,20,0,0,0,50,30/); + done(); + }); + }); });