最近在用jquery的flot画图,折线图饼图都没啥问题,一到柱状图就来事了,如果多个数据源,柱子都重叠到一起了,像这样:
度娘谷哥搜了一大圈,找了一个插件,专门处理这种情况的,但是郁闷的调了半天愣是没反应,该什么样还什么样,眼看工期将至,一咬牙,看源码吧。原来这个插件是在动态调整每个bar的barLeft属性,见代码红色处(jquery.flot.multibar.js):
(function ($) {
function init(plot) {
var multiple = true;
var sArray = [];
var totWidth = 0;
function procRawData(plot, series, data, datapoints) {
if(series.bars.show) {
sArray.push(series);
}
}
function procDatapoints(plot, series, datapoints) {
//Ensure we only process these once
if(series.bars.show && series.bars.barLeft==undefined) {
if(totWidth==0) {
for(var j = 0; j < sArray.length; j++) {
totWidth+=sArray[j].bars.barWidth;
}
}
var runWidth=0;
for(var k = 0; k < sArray.length; k++) {
s=sArray[k];
if(s==series) {
break;
}
runWidth+=s.bars.barWidth;
}
series.bars.barLeft = runWidth-(totWidth/2);
}
}
function checkMultipleBarsEnabled(plot, options) {
if (options.multiplebars) {
multiple = options.multiplebars;
sArray=[];
totWidth=0;
plot.hooks.processRawData.push(procRawData);
plot.hooks.processDatapoints.push(procDatapoints);
}
}
plot.hooks.processOptions.push(checkMultipleBarsEnabled);
}
var options = { multiplebars: true };
$.plot.plugins.push({
init: init,
options: options,
name: "multiplebars",
version: "0.1"
});
})(jQuery);
但是可恶的是,jquery.flot.js自己却重新给barLeft赋值了,见红色代码(jquery.flot.js):
function drawSeriesBars(series) {
function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) {
var points = datapoints.points, ps = datapoints.pointsize;
for (var i = 0; i < points.length; i += ps) {
if (points[i] == null)
continue;
drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
}
}
ctx.save();
ctx.translate(plotOffset.left, plotOffset.top);
// FIXME: figure out a way to add shadows (for instance along the right edge)
ctx.lineWidth = series.bars.lineWidth;
ctx.strokeStyle = series.color;
var barLeft;
switch (series.bars.align) {
case "left":
barLeft = 0;
break;
case "right":
barLeft = -series.bars.barWidth;
break;
default:
barLeft = -series.bars.barWidth / 2;
}
var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, fillStyleCallback, series.xaxis, series.yaxis);
ctx.restore();
}
所以,果断的加上判断,要用bars自己的barLeft:
function drawSeriesBars(series) {
function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) {
var points = datapoints.points, ps = datapoints.pointsize;
for (var i = 0; i < points.length; i += ps) {
if (points[i] == null)
continue;
drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);
}
}
ctx.save();
ctx.translate(plotOffset.left, plotOffset.top);
// FIXME: figure out a way to add shadows (for instance along the right edge)
ctx.lineWidth = series.bars.lineWidth;
ctx.strokeStyle = series.color;
var barLeft;
if(series.bars.barLeft != undefined){
barLeft = series.bars.barLeft;
}else{
switch (series.bars.align) {
case "left":
barLeft = 0;
break;
case "right":
barLeft = -series.bars.barWidth;
break;
default:
barLeft = -series.bars.barWidth / 2;
}
}
var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, fillStyleCallback, series.xaxis, series.yaxis);
ctx.restore();
}
终于显示成如下样子了: