honeyth 2015-04-23
最近在用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(); }
终于显示成如下样子了: