Commit 2015ca3a authored by olau@iola.dk's avatar olau@iola.dk

Added more members to the Plot object + a few cleanups

git-svn-id: https://flot.googlecode.com/svn/trunk@57 1e0a6537-2640-0410-bfb7-f154510ff394
parent 47eb2cb0
...@@ -513,6 +513,37 @@ members: ...@@ -513,6 +513,37 @@ members:
- getPlotOffset() - getPlotOffset()
Gets the offset that the grid has within the canvas as an object Gets the offset that the grid has within the canvas as an object
with the members left, right, top, bottom. I.e., if you draw a with the members "left", "right", "top", "bottom". I.e., if you draw a
circle on the canvas with the center placed at (left, top), its circle on the canvas with the center placed at (left, top), its
center will be at the top-most, left corner of the grid. center will be at the top-most, left corner of the grid.
- setData(data)
You can use this to reset the data used. Note that axis scaling,
ticks, legend etc. will not be recomputed (use setupGrid() to do
that). You'll probably want to call draw() afterwards.
- getData()
Returns the data currently used. The data series returned are
normalized with missing settings filled in. So for instance to
find out what color Flot has assigned to the data series, you
could do this:
var series = plot.getData();
for (var i = 0; i < series.length; ++i)
alert([i].color);
- setupGrid()
Recalculate and set axis scaling, ticks, legend etc.
Note that because of the drawing model of the canvas, this
function will immediately redraw (actually reinsert in the DOM)
the labels and the legend, but not the actual tick lines because
they're drawn on the canvas. You need to call draw() to get the
canvas redrawn.
- draw()
Redraws the canvas.
...@@ -15,6 +15,11 @@ Support for colored background areas via grid.coloredAreas. Specify an ...@@ -15,6 +15,11 @@ Support for colored background areas via grid.coloredAreas. Specify an
array of { x1, y1, x2, y2 } objects or a function that returns these array of { x1, y1, x2, y2 } objects or a function that returns these
given { xmin, xmax, ymin, ymax }. given { xmin, xmax, ymin, ymax }.
More members on the plot object (report by Chris Davies and others).
"getData" for inspecting the assigned settings on data series (e.g.
color) and "setData", "setupGrid" and "draw" for updating the contents
without a total replot.
The default number of ticks to aim for is now dependent on the size of The default number of ticks to aim for is now dependent on the size of
the plot in pixels. Support for customizing tick interval sizes the plot in pixels. Support for customizing tick interval sizes
directly with axis.minTickSize and axis.tickSize. directly with axis.minTickSize and axis.tickSize.
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
scaled.</p> scaled.</p>
<script id="source" language="javascript" type="text/javascript"> <script id="source" language="javascript" type="text/javascript">
var plot;
$(function () { $(function () {
var d1 = []; var d1 = [];
for (var i = 0; i < 14; i += 0.5) for (var i = 0; i < 14; i += 0.5)
...@@ -30,7 +31,7 @@ $(function () { ...@@ -30,7 +31,7 @@ $(function () {
// a null signifies separate line segments // a null signifies separate line segments
var d3 = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]]; var d3 = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]];
$.plot($("#placeholder"), [ d1, d2, d3 ]); plot = $.plot($("#placeholder"), [ d1, d2, d3 ]);
}); });
</script> </script>
......
...@@ -88,34 +88,34 @@ ...@@ -88,34 +88,34 @@
yLabelMaxWidth = 0, yLabelMaxHeight = 0, xLabelBoxWidth = 0, yLabelMaxWidth = 0, yLabelMaxHeight = 0, xLabelBoxWidth = 0,
canvasWidth = 0, canvasHeight = 0, canvasWidth = 0, canvasHeight = 0,
plotWidth = 0, plotHeight = 0, plotWidth = 0, plotHeight = 0,
hozScale = 0, vertScale = 0; hozScale = 0, vertScale = 0,
// dedicated to storing data for buggy standard compliance cases // dedicated to storing data for buggy standard compliance cases
var workarounds = {}; workarounds = {};
this.setData = setData;
this.setupGrid = setupGrid;
this.draw = draw;
this.clearSelection = clearSelection;
this.setSelection = setSelection;
this.getCanvas = function() { return canvas; };
this.getPlotOffset = function() { return plotOffset; };
this.getData = function() { return series; };
this.getAxes = function() { return { xaxis: xaxis, yaxis: yaxis }; };
// initialize // initialize
series = parseData(data_);
parseOptions(options_); parseOptions(options_);
fillInSeriesOptions(); setData(data_);
constructCanvas(); constructCanvas();
bindEvents(); setupGrid();
findDataRanges();
setRange(xaxis, options.xaxis);
prepareTickGeneration(xaxis, options.xaxis);
setTicks(xaxis, options.xaxis);
extendXRangeIfNeededByBar();
setRange(yaxis, options.yaxis);
prepareTickGeneration(yaxis, options.yaxis);
setTicks(yaxis, options.yaxis);
setSpacing();
draw(); draw();
insertLegend();
this.getCanvas = function() { return canvas; };
this.getPlotOffset = function() { return plotOffset; }; function setData(d) {
this.clearSelection = clearSelection; series = parseData(d);
this.setSelection = setSelection;
fillInSeriesOptions();
processData();
}
function parseData(d) { function parseData(d) {
var res = []; var res = [];
...@@ -145,47 +145,80 @@ ...@@ -145,47 +145,80 @@
options.yaxis.ticks = options.yaxis.noTicks; options.yaxis.ticks = options.yaxis.noTicks;
} }
function constructCanvas() { function fillInSeriesOptions() {
canvasWidth = target.width(); var i;
canvasHeight = target.height();
target.html(""); // clear target
target.css("position", "relative"); // for positioning labels and overlay
if (canvasWidth <= 0 || canvasHeight <= 0) // collect what we already got of colors
throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight; var neededColors = series.length;
var usedColors = [];
var assignedColors = [];
for (i = 0; i < series.length; ++i) {
var sc = series[i].color;
if (sc != null) {
--neededColors;
if (typeof sc == "number")
assignedColors.push(sc);
else
usedColors.push(parseColor(series[i].color));
}
}
// the canvas // we might need to generate more colors if higher indices
canvas = $('<canvas width="' + canvasWidth + '" height="' + canvasHeight + '"></canvas>').appendTo(target).get(0); // are assigned
if ($.browser.msie) // excanvas hack for (i = 0; i < assignedColors.length; ++i) {
canvas = window.G_vmlCanvasManager.initElement(canvas); neededColors = Math.max(neededColors, assignedColors[i] + 1);
ctx = canvas.getContext("2d"); }
// overlay canvas for interactive features // produce colors as needed
overlay = $('<canvas style="position:absolute;left:0px;top:0px;" width="' + canvasWidth + '" height="' + canvasHeight + '"></canvas>').appendTo(target).get(0); var colors = [];
if ($.browser.msie) // excanvas hack var variation = 0;
overlay = window.G_vmlCanvasManager.initElement(overlay); i = 0;
octx = overlay.getContext("2d"); while (colors.length < neededColors) {
var c;
if (options.colors.length == i) // check degenerate case
c = new Color(100, 100, 100);
else
c = parseColor(options.colors[i]);
// we include the canvas in the event holder too, because IE 7 // vary color if needed
// sometimes has trouble with the stacking order var sign = variation % 2 == 1 ? -1 : 1;
eventHolder = $([overlay, canvas]); var factor = 1 + sign * Math.ceil(variation / 2) * 0.2;
c.scale(factor, factor, factor);
// FIXME: if we're getting to close to something else,
// we should probably skip this one
colors.push(c);
++i;
if (i >= options.colors.length) {
i = 0;
++variation;
}
} }
function bindEvents() { // fill in the options
if (options.selection.mode != null) { var colori = 0, s;
eventHolder.mousedown(onMouseDown); for (i = 0; i < series.length; ++i) {
s = series[i];
// FIXME: temp. work-around until jQuery bug 1871 is fixed // assign colors
eventHolder.each(function () { if (s.color == null) {
this.onmousemove = onMouseMove; s.color = colors[colori].toString();
}); ++colori;
} }
else if (typeof s.color == "number")
s.color = colors[s.color].toString();
if (options.grid.clickable) // copy the rest
eventHolder.click(onClick); s.lines = $.extend(true, {}, options.lines, s.lines);
s.points = $.extend(true, {}, options.points, s.points);
s.bars = $.extend(true, {}, options.bars, s.bars);
if (s.shadowSize == null)
s.shadowSize = options.shadowSize;
}
} }
function findDataRanges() { function processData() {
xaxis.datamin = yaxis.datamin = Number.MAX_VALUE; xaxis.datamin = yaxis.datamin = Number.MAX_VALUE;
xaxis.datamax = yaxis.datamax = Number.MIN_VALUE; xaxis.datamax = yaxis.datamax = Number.MIN_VALUE;
...@@ -224,6 +257,63 @@ ...@@ -224,6 +257,63 @@
yaxis.datamax = 1; yaxis.datamax = 1;
} }
function constructCanvas() {
canvasWidth = target.width();
canvasHeight = target.height();
target.html(""); // clear target
target.css("position", "relative"); // for positioning labels and overlay
if (canvasWidth <= 0 || canvasHeight <= 0)
throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight;
// the canvas
canvas = $('<canvas width="' + canvasWidth + '" height="' + canvasHeight + '"></canvas>').appendTo(target).get(0);
if ($.browser.msie) // excanvas hack
canvas = window.G_vmlCanvasManager.initElement(canvas);
ctx = canvas.getContext("2d");
// overlay canvas for interactive features
overlay = $('<canvas style="position:absolute;left:0px;top:0px;" width="' + canvasWidth + '" height="' + canvasHeight + '"></canvas>').appendTo(target).get(0);
if ($.browser.msie) // excanvas hack
overlay = window.G_vmlCanvasManager.initElement(overlay);
octx = overlay.getContext("2d");
// we include the canvas in the event holder too, because IE 7
// sometimes has trouble with the stacking order
eventHolder = $([overlay, canvas]);
// bind events
if (options.selection.mode != null) {
eventHolder.mousedown(onMouseDown);
// FIXME: temp. work-around until jQuery bug 1871 is fixed
eventHolder.each(function () {
this.onmousemove = onMouseMove;
});
}
if (options.grid.clickable)
eventHolder.click(onClick);
}
function setupGrid() {
// x axis
setRange(xaxis, options.xaxis);
prepareTickGeneration(xaxis, options.xaxis);
setTicks(xaxis, options.xaxis);
extendXRangeIfNeededByBar();
// y axis
setRange(yaxis, options.yaxis);
prepareTickGeneration(yaxis, options.yaxis);
setTicks(yaxis, options.yaxis);
setSpacing();
insertLabels();
insertLegend();
}
function setRange(axis, axisOptions) { function setRange(axis, axisOptions) {
var min = axisOptions.min != null ? axisOptions.min : axis.datamin; var min = axisOptions.min != null ? axisOptions.min : axis.datamin;
var max = axisOptions.max != null ? axisOptions.max : axis.datamax; var max = axisOptions.max != null ? axisOptions.max : axis.datamax;
...@@ -648,7 +738,6 @@ ...@@ -648,7 +738,6 @@
function draw() { function draw() {
drawGrid(); drawGrid();
drawLabels();
for (var i = 0; i < series.length; i++) { for (var i = 0; i < series.length; i++) {
drawSeries(series[i]); drawSeries(series[i]);
} }
...@@ -666,6 +755,7 @@ ...@@ -666,6 +755,7 @@
var i; var i;
ctx.save(); ctx.save();
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.translate(plotOffset.left, plotOffset.top); ctx.translate(plotOffset.left, plotOffset.top);
// draw background, if any // draw background, if any
...@@ -749,9 +839,11 @@ ...@@ -749,9 +839,11 @@
} }
} }
function drawLabels() { function insertLabels() {
target.find(".tickLabels").remove();
var i, tick; var i, tick;
var html = '<div style="font-size:smaller;color:' + options.grid.color + '">'; var html = '<div class="tickLabels" style="font-size:smaller;color:' + options.grid.color + '">';
// do the x-axis // do the x-axis
for (i = 0; i < xaxis.ticks.length; ++i) { for (i = 0; i < xaxis.ticks.length; ++i) {
...@@ -774,79 +866,6 @@ ...@@ -774,79 +866,6 @@
target.append(html); target.append(html);
} }
function fillInSeriesOptions() {
var i;
// collect what we already got of colors
var neededColors = series.length;
var usedColors = [];
var assignedColors = [];
for (i = 0; i < series.length; ++i) {
var sc = series[i].color;
if (sc != null) {
--neededColors;
if (typeof sc == "number")
assignedColors.push(sc);
else
usedColors.push(parseColor(series[i].color));
}
}
// we might need to generate more colors if higher indices
// are assigned
for (i = 0; i < assignedColors.length; ++i) {
neededColors = Math.max(neededColors, assignedColors[i] + 1);
}
// produce colors as needed
var colors = [];
var variation = 0;
i = 0;
while (colors.length < neededColors) {
var c;
if (options.colors.length == i) // check degenerate case
c = new Color(100, 100, 100);
else
c = parseColor(options.colors[i]);
// vary color if needed
var sign = variation % 2 == 1 ? -1 : 1;
var factor = 1 + sign * Math.ceil(variation / 2) * 0.2;
c.scale(factor, factor, factor);
// FIXME: if we're getting to close to something else,
// we should probably skip this one
colors.push(c);
++i;
if (i >= options.colors.length) {
i = 0;
++variation;
}
}
// fill in the options
var colori = 0;
for (i = 0; i < series.length; ++i) {
var s = series[i];
// assign colors
if (s.color == null) {
s.color = colors[colori].toString();
++colori;
}
else if (typeof s.color == "number")
s.color = colors[s.color].toString();
// copy the rest
s.lines = $.extend(true, {}, options.lines, s.lines);
s.points = $.extend(true, {}, options.points, s.points);
s.bars = $.extend(true, {}, options.bars, s.bars);
if (s.shadowSize == null)
s.shadowSize = options.shadowSize;
}
}
function drawSeries(series) { function drawSeries(series) {
if (series.lines.show || (!series.bars.show && !series.points.show)) if (series.lines.show || (!series.bars.show && !series.points.show))
drawSeriesLines(series); drawSeriesLines(series);
...@@ -1256,6 +1275,8 @@ ...@@ -1256,6 +1275,8 @@
} }
function insertLegend() { function insertLegend() {
target.find(".legend").remove();
if (!options.legend.show) if (!options.legend.show)
return; return;
...@@ -1298,7 +1319,7 @@ ...@@ -1298,7 +1319,7 @@
pos += 'right:' + (m + plotOffset.right) + 'px;'; pos += 'right:' + (m + plotOffset.right) + 'px;';
else if (p.charAt(1) == "w") else if (p.charAt(1) == "w")
pos += 'left:' + (m + plotOffset.bottom) + 'px;'; pos += 'left:' + (m + plotOffset.bottom) + 'px;';
var div = $('<div class="legend" style="position:absolute;z-index:2;' + pos +'">' + table + '</div>').appendTo(target); var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(target);
if (options.legend.backgroundOpacity != 0.0) { if (options.legend.backgroundOpacity != 0.0) {
// put in the transparent background // put in the transparent background
// separately to avoid blended labels and // separately to avoid blended labels and
...@@ -1309,10 +1330,11 @@ ...@@ -1309,10 +1330,11 @@
if (options.grid.backgroundColor != null) if (options.grid.backgroundColor != null)
tmp = options.grid.backgroundColor; tmp = options.grid.backgroundColor;
else else
tmp = extractColor(div); tmp = extractColor(legend);
c = parseColor(tmp).adjust(null, null, null, 1).toString(); c = parseColor(tmp).adjust(null, null, null, 1).toString();
} }
$('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').appendTo(target).css('opacity', options.legend.backgroundOpacity); var div = legend.children();
$('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment