flot转身为帕累托图

工作需要,需要绘制帕累托图,并用js实现在web页面上。所以flot插件又是被各种改造……

多级帕累托图,改造后效果

 

单级帕累托图,其实蛮好实现的。因为flot本来就支持柱状图与电线图在同一界面上出现。

在绘制单级帕累托图时,我的作法是先绘制柱状图。以左边Y轴作为柱状图的Y轴。然后绘制点线图,点线图由于代表的是一个累积量。所以,以右边为y轴作为点线图的Y轴。先计算数据总和,定义右边坐标轴最大值。至于坐标轴上显示的百分数,我们可以将数轴等分,计算百分比并给出坐标轴Ticks。实际上,右边坐标轴的总长度不是一个百分数,而是数据的总和。点线图的累积量由此也可以直接用数据的累积量计算不需要考虑累积百分数。节省计算过程。只是在坐标轴定义时,可以把每一个累积数据转换为百分数来计算。直接用实际值代替百分比。

//单级帕累托图参数赋值并绘制
var DataLength = 0;
if (DataTable != null && DataTable.length > 0) {
DataLength = DataTable.length;
xmax = DataLength;
xmin = 0;

//产生柱状图
var xp = 0;
var datacur = 0;
var dserice = [];
for (var i = 0; i < DataTable.length; i++) {
var d = [];
d.push([xp, DataTable[i].Data]);
var index = parseInt(DataTable[i].Rank) - 1;
if (index >= Color.length) {
index = index - Color.length;
}
data.push({ color: Color[index], data: d, stack: false, bars: { show: true, lineWidth: 0.5, barWidth: barwith, align: "left" }, xaxis: 1, yaxis: 1 });
xp = xp + barwith;
datacur = datacur + DataTable[i].Data;
xticks.push([xp, DataTable[i].Name]);
//产生曲线数据点
dserice.push([xp, datacur]);
}

dserice.push([xp, datacur]);
data.push({ color: Color[1], data: dserice, xaxis: 1, yaxis: 2, lines: { show: true, fill: false }, points: { show: true, radius: 2} });
//添加点线图中,点的Tips
var percent = 0;
for (var i = 0; i < DataTable.length; i++) {
var percent = (percent + DataTable[i].Data / datacur); //保留两位小数
percent = Math.round(percent * 10000) / 10000;
//percent=(percent*100).toFixed(2);
DotTips.push(percent * 100 + "%");
}
ymaxR = datacur;
yminR = 0;
var yRatio = ymaxR / yPortion; //x轴每一分实际的长度
var yPercent = 100 / yPortion; //x轴每一份的百分数
var yr = 0;
var yp = 0;
for (var i = 0; i < yPortion; i++) {
yticks.push([yr - barLabelRatio, String(yp) + "%"]);
yr += yRatio;
yp += yPercent;
}
yticks.push([yr - barLabelRatio, String(yp) + "%"]);
var options = {
grid: { hoverable: true, clickable: true },

legend: {
show: true
},
xaxes: [
{ position: 'bottom', show: true, ticks: xticks },

],
yaxes: [
{ position: 'left', min: yminR, max: ymaxR },
{ position: 'right', ticks: yticks }

]
};

BarTips = xticks;
var plot = $.plot($(placeholder), data, options);

}

 

 

 绘制Pareto的方法为   DrawParetoChart(ParetoScale, DataTable, placeholder); ParetoScale表示pareto的级数,DateTable数据形式类似于  DataTable1.push({ Rank: "1", Data: 15, Name: "marks1" });,placeholder是需要绘制Pareto图的Div的id.

DataTable是由Ajax加载过来的。此时,数据已经由C#排序好。所以,该伪pareto的js控件中,没有进行数据排序。

  多级pareto图中,实际上就是在绘制柱状图。~一堆柱状图。

//多级帕累托图参数赋值并绘制
var DataLength = 0; //多级数据的总长度
if (DataTable != null && DataTable.length > 0) {
//求数据的总长度
DataLength = DataTable.length;
for (var i = 0; i < DataTable.length; i++) {
if (DataTable[i].Rank==1) {
xmax += DataTable[i].Data;
}

}
// xmax = DataTable[0].Data + 20;
xmin = 0;
//计算数轴上y的最大值与最小值
if (DataLength != 0) {
if (DataLength - 1 > ymax) {
ymax = DataLength - 1;
}
ymin = 0;
}

var xRatio = xmax / xPortion; //x轴每一分实际的长度
var xPercent = 100 / xPortion; //x轴每一份的百分数
var xr = 0;
var xp = 0;
for (var i = 0; i < xPortion; i++) {
if (i == 0) {
xticks.push([0, String(xp) + "%"]);
}
else {
xticks.push([xr - barLabelRatio, String(xp) + "%"]);
}

xr += xRatio;
xp += xPercent;
}
xticks.push([xr - barLabelRatio, String(xp) + "%"]);
var yp = ymax;

for (var i = 0; i < DataTable.length; i++) {
var d = [];
d.push([DataTable[i].Data, yp]);
var index = parseInt(DataTable[i].Rank) - 1;
if (index >= Color.length) {
index = index - Color.length;
}
//添加最后一个数据
data.push({ color: Color[index], data: d });
var Tickspan = (ParetoScale + 1 - DataTable[i].Rank) * 10;
//多级数据时为左边的marks分级
yticks.push([yp + barLabelRatio, DataTable[i].Name + "<span style='margin-left:" + Tickspan + "px;'></span>"]);
yp = yp - barwith;
}
var options = {
series: {
stack: false,
bars: { lineWidth: 0.5, show: true, barWidth: barwith, horizontal: true, align: "left"
}
},
grid: { hoverable: true, clickable: true },
yaxis: { ticks: yticks },
xaxis: { position: 'bottom', mode: null, show: true, min: xmin, max: xmax, ticks: xticks },
legend: {
show: true
}
};
var plot = $.plot($(placeholder), data, options);
}

多级pareto的左边坐标轴分级:

var Tickspan = (ParetoScale + 1 - DataTable[i].Rank) * 10;
//多级数据时为左边的marks分级
yticks.push([yp + barLabelRatio, DataTable[i].Name + "<span style='margin-left:" + Tickspan + "px;'></span>"]);实际上就是给人家加了一个span用来占位。

在柱状图的上方显示数据值:在flot.js源代码的2113行中添加

if (horizontal) {
$('<div>' + x + '</div>').css({
position: 'absolute',
display: 'inline',
top: bottom,
left: textleft+25,
padding: '2px',
'background-color': '',
opacity: 0.80
}).appendTo(c.canvas);

}
else {
$('<div>' + y + '</div>').css({
position: 'absolute',
display: 'inline',
top: top-20,
left: left+axisx.labelWidth/2,
padding: '2px',
'background-color': '',
opacity: 0.80
}).appendTo(c.canvas);
}。其实就是按照添加ToolTip的方式在固定的位置添加所需要的数据值。此时需要注意的是,我们再横坐标定位时需要考虑他的labelWidth。

 

与其说是转身为Pareto,不如说就是一个伪Pareto,因为它没有涉及到数据的排序,如果传来的参数里面DateTable,数据格式很乱,当然也会绘制图表,但是就长的不怎地像那个Pareto了。所以,需要代码将数据排序排序排序

posted @ 2012-06-18 15:38  小兔兔  阅读(1017)  评论(1编辑  收藏  举报