diff --git a/API.txt b/API.txt index d6c04ef..32108dc 100644 --- a/API.txt +++ b/API.txt @@ -409,7 +409,7 @@ Customizing the data series show: boolean lineWidth: number fill: boolean or number - fillColor: color + fillColor: null or color/gradient } points: { @@ -449,12 +449,13 @@ points), the fill color is auto-set to the color of the data series. You can adjust the opacity of the fill by setting fill to a number between 0 (fully transparent) and 1 (fully opaque). -"barWidth" is the width of the bars in units of the x axis, contrary -to most other measures that are specified in pixels. For instance, for -time series the unit is milliseconds so 24 * 60 * 60 * 1000 produces -bars with the width of a day. "align" specifies whether a bar should -be left-aligned (default) or centered on top of the value it -represents. +For bars, fillColor can be a gradient, see the gradient documentation +below. "barWidth" is the width of the bars in units of the x axis, +contrary to most other measures that are specified in pixels. For +instance, for time series the unit is milliseconds so 24 * 60 * 60 * +1000 produces bars with the width of a day. "align" specifies whether +a bar should be left-aligned (default) or centered on top of the value +it represents. The "colors" array specifies a default color theme to get colors for the data series from. You can specify as many colors as you like, like @@ -655,6 +656,15 @@ black to gray like this: backgroundColor: { colors: ["#000", "#999"] } } +For the series you can specify the gradient as an object that +specifies the scaling of the brightness and the opacity of the series +color, e.g. + + { colors: [{ opacity: 0.8 }, { brightness: 0.6, opacity: 0.8 } ] + +where the first color simply has its alpha scaled, whereas the second +is also darkened. + Flot currently only supports vertical gradients drawn from top to bottom because that's what works with IE. diff --git a/NEWS.txt b/NEWS.txt index 4fd213e..09cefac 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -28,16 +28,17 @@ Changes: - Added "borderColor" option to the grid (patch from Amaury Chamayou and patch from Mike R. Williamson). -- Added support for gradient background for the grid, take a look at +- Added support for gradient backgrounds for the grid, take a look at the "setting options" example (based on patch from Amaury Chamayou, issue 90). +- Gradient bars (suggestion by stefpet). + - Added a "plotunselected" event which is triggered when the selection is removed, see "selection" example (suggestion by Meda Ugo); - The option legend.margin can now specify horizontal and vertical margins independently (suggestion by someone who's annoyed). - Bug fixes: diff --git a/jquery.flot.js b/jquery.flot.js index 34d43a6..daabedd 100644 --- a/jquery.flot.js +++ b/jquery.flot.js @@ -858,7 +858,7 @@ // draw background, if any if (options.grid.backgroundColor) { - ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor); + ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight); ctx.fillRect(0, 0, plotWidth, plotHeight); } @@ -1270,9 +1270,11 @@ ctx.lineWidth = lw; ctx.strokeStyle = series.color; - setFillStyle(series.lines, series.color); - if (series.lines.fill) + var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight); + if (fillStyle) { + ctx.fillStyle = fillStyle; plotLineArea(series.data, series.xaxis, series.yaxis); + } if (lw > 0) plotLine(series.data, 0, series.xaxis, series.yaxis); @@ -1280,7 +1282,7 @@ } function drawSeriesPoints(series) { - function plotPoints(data, radius, fill, axisx, axisy) { + function plotPoints(data, radius, fillStyle, axisx, axisy) { for (var i = 0; i < data.length; ++i) { if (data[i] == null) continue; @@ -1291,8 +1293,10 @@ ctx.beginPath(); ctx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, true); - if (fill) + if (fillStyle) { + ctx.fillStyle = fillStyle; ctx.fill(); + } ctx.stroke(); } } @@ -1331,13 +1335,13 @@ ctx.lineWidth = series.points.lineWidth; ctx.strokeStyle = series.color; - setFillStyle(series.points, series.color); - plotPoints(series.data, series.points.radius, series.points.fill, + plotPoints(series.data, series.points.radius, + getFillStyle(series.points, series.color), series.xaxis, series.yaxis); ctx.restore(); } - function drawBar(x, y, barLeft, barRight, offset, fill, axisx, axisy, c) { + function drawBar(x, y, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c) { var drawLeft = true, drawRight = true, drawTop = true, drawBottom = false, left = x + barLeft, right = x + barRight, @@ -1376,24 +1380,27 @@ drawTop = false; } + left = axisx.p2c(left); + bottom = axisy.p2c(bottom); + right = axisx.p2c(right); + top = axisy.p2c(top); + // fill the bar - if (fill) { + if (fillStyleCallback) { c.beginPath(); - c.moveTo(axisx.p2c(left), axisy.p2c(bottom) + offset); - c.lineTo(axisx.p2c(left), axisy.p2c(top) + offset); - c.lineTo(axisx.p2c(right), axisy.p2c(top) + offset); - c.lineTo(axisx.p2c(right), axisy.p2c(bottom) + offset); + c.moveTo(left, bottom); + c.lineTo(left, top); + c.lineTo(right, top); + c.lineTo(right, bottom); + ctx.fillStyle = fillStyleCallback(bottom, top); c.fill(); } // draw outline if (drawLeft || drawRight || drawTop || drawBottom) { c.beginPath(); - left = axisx.p2c(left); - bottom = axisy.p2c(bottom); - right = axisx.p2c(right); - top = axisy.p2c(top); - + + // FIXME: inline moveTo is buggy with excanvas c.moveTo(left, bottom + offset); if (drawLeft) c.lineTo(left, top + offset); @@ -1416,11 +1423,11 @@ } function drawSeriesBars(series) { - function plotBars(data, barLeft, barRight, offset, fill, axisx, axisy) { + function plotBars(data, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) { for (var i = 0; i < data.length; i++) { if (data[i] == null) continue; - drawBar(data[i][0], data[i][1], barLeft, barRight, offset, fill, axisx, axisy, ctx); + drawBar(data[i][0], data[i][1], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx); } } @@ -1428,7 +1435,7 @@ ctx.translate(plotOffset.left, plotOffset.top); ctx.lineJoin = "round"; - // FIXME: figure out a way to add shadows + // FIXME: figure out a way to add shadows (for instance along the right edge) /* var bw = series.bars.barWidth; var lw = series.bars.lineWidth; @@ -1446,25 +1453,24 @@ ctx.lineWidth = series.bars.lineWidth; ctx.strokeStyle = series.color; - setFillStyle(series.bars, series.color); var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; - plotBars(series.data, barLeft, barLeft + series.bars.barWidth, 0, series.bars.fill, series.xaxis, series.yaxis); + var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; + plotBars(series.data, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis); ctx.restore(); } - function setFillStyle(obj, seriesColor) { - var fill = obj.fill; + function getFillStyle(filloptions, seriesColor, bottom, top) { + var fill = filloptions.fill; if (!fill) - return; + return null; + + if (filloptions.fillColor) + return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); - if (obj.fillColor) - ctx.fillStyle = obj.fillColor; - else { - var c = parseColor(seriesColor); - c.a = typeof fill == "number" ? fill : 0.4; - c.normalize(); - ctx.fillStyle = c.toString(); - } + var c = parseColor(seriesColor); + c.a = typeof fill == "number" ? fill : 0.4; + c.normalize(); + return c.toString(); } function insertLegend() { @@ -1872,10 +1878,10 @@ octx.lineJoin = "round"; octx.lineWidth = series.bars.lineWidth; octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); - octx.fillStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); + var fillStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString(); var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; drawBar(point[0], point[1], barLeft, barLeft + series.bars.barWidth, - 0, true, series.xaxis, series.yaxis, octx); + 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx); } function setPositionFromEvent(pos, e) { @@ -2023,17 +2029,19 @@ Math.abs(selection.second.y - selection.first.y) >= minSize; } - function getColorOrGradient(spec) { + function getColorOrGradient(spec, bottom, top, defaultColor) { if (typeof spec == "string") return spec; else { // assume this is a gradient spec; IE currently only // supports a simple vertical gradient properly, so that's // what we support too - var gradient = ctx.createLinearGradient(0, 0, 0, plotHeight); + var gradient = ctx.createLinearGradient(0, top, 0, bottom); - for (var i = 0, l = spec.colors.length; i < l; ++i) - gradient.addColorStop(i / (l - 1), spec.colors[i]); + for (var i = 0, l = spec.colors.length; i < l; ++i) { + var c = spec.colors[i]; + gradient.addColorStop(i / (l - 1), typeof c == "string" ? c : parseColor(defaultColor).scale(c.brightness, c.brightness, c.brightness, c.opacity)); + } return gradient; }