I actualy have a pie charts with multiple series of data each of them represented by a pie chart (see JSFiddle link).
I'm looking for a way to implement an "automatic" calculation of optimal size for each Pie Charts and an optimal position in order to render all of them in 1 single container in a generic way.
I've Actualy came up with a begining of solution but it's realy not optimal.
Either I didn't understand how Highcharts work when generating charts, or there's to much unknown value for my system to be able to make the calculation or both.
Please note the generator only work for 1 to 6 diffrent series of data if using more series it will fail to get placement as I didn't made the calculation.
Also it's actualy confirmed to work only on containers of these size :
- width: 340px height: 170px
- width: 680px height: 170px
On container with highter width or height the system will fail to calculate the position.
That's actualy a part of why i came looking for ideas on how to get optimal and generic position calculator.
Here's the code I came with and a JSFiddle link after the code sample.
// Pie Chart Class
var pieChart = {
create: function(_title, _data, _color, _height, _width) {
return (function() {
var type = 'pie';
var title = _title || "defaultName";
var color = _color || "#EBEBEB";
var height = _height || 170;
var width = _width || 340;
var series = [];
var chart;
var sizeData = getSize(height, width);
if (_data)
newSeries(_data);
// Public functions
function newSeries(_data) {
var _datas = [];
for (var dataSet in _data) {
if (_data.hasOwnProperty(dataSet) && (color != null && color != undefined)) {
_datas.push({
name: dataSet,
y: _data[dataSet],
});
}
}
series.push({
data: _datas,
borderWidth: 0,
center: []
});
setPos(series.length);
}
function Series() {
return (JSON.stringify(series));
}
function drawOn(item) {
if (!item || !document.getElementById(item) && !chart)
return (null);
else {
chart = new Highcharts.Chart({
chart: {
renderTo: item,
backgroundColor: color,
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: title
},
plotOptions: {
pie: {
allowPointSelect: false,
borderWidth: 0,
dataLabels: {
distance: -1,
enabled: true,
format: '<b>{point.name}</b>: {point.y}',
style: {
color: 'black'
}
},
size: sizeData.size
}
},
series: JSON.parse(Series())
});
}
}
// Private functions
function setPos(_len) {
if (_len == 1)
series[0].center = [sizeData.center, sizeData.h];
else if (_len == 2) {
series[0].center = [sizeData.second, sizeData.h];
series[1].center = [sizeData.fourth, sizeData.h];
} else if (_len == 3) {
series[0].center = [sizeData.w1, sizeData.h];
series[1].center = [sizeData.center, sizeData.h];
series[2].center = [sizeData.w6, sizeData.h];
} else if (_len == 4) {
series[0].center = [(sizeData.w1 + sizeData.w2) / 2, sizeData.h];
series[1].center = [sizeData.w3, sizeData.h];
series[2].center = [(sizeData.w4 + sizeData.w5) / 2, sizeData.h];
series[3].center = [sizeData.w6, sizeData.h];
} else if (_len == 5) {
series[0].center = [sizeData.w1, sizeData.h];
series[1].center = [sizeData.second, sizeData.h];
series[2].center = [sizeData.center, sizeData.h];
series[3].center = [sizeData.fourth, sizeData.h];
series[4].center = [sizeData.w6, sizeData.h];
} else if (_len == 6) {
series[0].center = [sizeData.w1, sizeData.h];
series[1].center = [sizeData.w2, sizeData.h];
series[2].center = [sizeData.w3, sizeData.h];
series[3].center = [sizeData.w4, sizeData.h];
series[4].center = [sizeData.w5, sizeData.h];
series[5].center = [sizeData.w6, sizeData.h];
}
}
function getSize(height, width) {
var nbChart = 6;
var diam;
var tmpWidth = width - 30;
if (nbChart == 1)
diam = height - ( height / 3);
else {
diam = (tmpWidth - (tmpWidth / nbChart)) / nbChart;
}
var test = (tmpWidth - (diam * nbChart));
var h = ((height - diam) / 2) / 2;
var w = diam + (test / (nbChart * 2));
var decal;
if (width >= 680)
decal = test / 10;
else
decal = 0;
return {
width: width,
height: height,
size: diam,
h: h,
w1: ((diam / 2) + decal),
w2: (((w) + diam / 2) + decal),
w3: (((w * 2) + diam / 2) + decal),
w4: (((w * 3) + diam / 2) + decal),
w5: (((w * 4) + diam / 2) + decal),
w6: (((w * 5) + diam / 2) + decal),
center: (((((w * 2) + diam / 2) + decal) + (((w * 3) + diam / 2) + decal)) / 2),
second: (((diam / 2) + decal) + (((((w * 2) + diam / 2) + decal) + (((w * 3) + diam / 2) + decal)) / 2)) / 2,
fourth: ((((((w * 2) + diam / 2) + decal) + (((w * 3) + diam / 2) + decal)) / 2) + (((w * 5) + diam / 2) + decal)) / 2
}
}
return {
Series: Series,
drawOn: drawOn,
newSeries: newSeries
}
})();
}
};
var crPie = pieChart.create('Test', {T1: 500, T2: 700}, "#EBEBEB", 170, 680);
crPie.newSeries({T1: 700, T2: 800});
crPie.drawOn('container');
(Here's the JSFiddle link : https://jsfiddle.net/jcL0wuwp/)
I do multiple research through internet but didn't found what i'm looking for , a way to get optimal placement position and size for data series.
(I know some part of the code is not optimals but my quetion is not about how to optimise or use classes in JS though i'm not agaisnt advises.)