Commit 81553910 authored by olau@iola.dk's avatar olau@iola.dk

Some cleanup in tick generation code, added support for aligning axes

with alignTicksWithAxis


git-svn-id: https://flot.googlecode.com/svn/trunk@258 1e0a6537-2640-0410-bfb7-f154510ff394
parent 947c1663
......@@ -195,6 +195,8 @@ Customizing the axes
labelHeight: null or number
tickLength: null or number
alignTicksWithAxis: null or number
}
All axes have the same kind of options. The following describes how to
......@@ -333,6 +335,14 @@ any extra axes use small ticks. A value of null means use the default,
while a number means small ticks of that length - set it to 0 to hide
the lines completely.
If you set "alignTicksWithAxis" to the number of another axis, e.g.
alignTicksWithAxis: 1, Flot will ensure that the autogenerated ticks
of this axis are aligned with the ticks of the other axis. This may
improve the looks, e.g. if you have one y axis to the left and one to
the right, because the grid lines will then match the ticks in both
ends. The trade-off is that the forced ticks won't necessarily be at
natural places.
Multiple axes
=============
......
......@@ -60,6 +60,10 @@ Changes:
Services, www.flightdataservices.com).
- Tick color is now auto-generated as the base color with some
transparency (unless you override it).
- Support for aligning ticks in the axes with "alignTicksWithAxis" to
ensure that they appear next to each other rather than in between,
at the expense of possibly awkward tick steps (sponsored by Flight
Data Services, www.flightdataservices.com).
- New hooks: drawSeries
......
......@@ -39,7 +39,12 @@ $(function () {
{
xaxes: [ { mode: 'time' } ],
yaxes: [ { min: 0 },
{ position: position, tickFormatter: euroFormatter } ],
{
// align if we are to the right
alignTicksWithAxis: position == "right" ? 1 : null,
position: position,
tickFormatter: euroFormatter
} ],
legend: { position: 'sw' }
});
}
......
......@@ -62,9 +62,10 @@
autoscaleMargin: null, // margin in % to add if auto-setting min/max
ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
tickFormatter: null, // fn: number -> string
tickLength: null, // size in pixels of ticks, or "full" for whole line
labelWidth: null, // size of tick labels in pixels
labelHeight: null,
tickLength: null, // size in pixels of ticks, or "full" for whole line
alignTicksWithAxis: null, // axis number or null for no sync
// mode specific options
tickDecimals: null, // no. of decimals, null means auto
......@@ -882,7 +883,8 @@
return a && (a.labelHeight || a.labelWidth);
});
if ($.inArray(axis, sameDirection) != 0 && tickLength == "full")
var innermost = $.inArray(axis, sameDirection) == 0;
if (!innermost && tickLength == "full")
tickLength = 5;
if (!isNaN(+tickLength))
......@@ -918,7 +920,7 @@
axis.position = pos;
axis.tickLength = tickLength;
axis.box.padding = padding;
axis.innermost = $.inArray(axis, samePosition) == 0;
axis.innermost = innermost;
}
function fixupAxisBox(axis) {
......@@ -947,11 +949,12 @@
for (k = 0; k < axes.length; ++k) {
setupTickGeneration(axes[k]);
setTicks(axes[k]);
snapRangeToTicks(axes[k], axes[k].ticks);
}
// find labelWidth/Height, do this on all, not just
// used as we might need to reserve space for unused
// to if their labelWidth/Height is set
// too if their labelWidth/Height is set
for (j = 0; j < xaxes.length; ++j)
measureTickLabels(xaxes[j]);
for (j = 0; j < yaxes.length; ++j)
......@@ -1107,10 +1110,7 @@
size *= magn;
}
if (opts.tickSize) {
size = opts.tickSize[0];
unit = opts.tickSize[1];
}
axis.tickSize = opts.tickSize || [size, unit];
generator = function(axis) {
var ticks = [],
......@@ -1148,7 +1148,7 @@
do {
prev = v;
v = d.getTime();
ticks.push({ v: v, label: axis.tickFormatter(v, axis) });
ticks.push(v);
if (unit == "month") {
if (tickSize < 1) {
// a bit complicated - we'll divide the month
......@@ -1238,10 +1238,8 @@
if (opts.minTickSize != null && size < opts.minTickSize)
size = opts.minTickSize;
if (opts.tickSize != null)
size = opts.tickSize;
axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec);
axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);
axis.tickSize = opts.tickSize || size;
generator = function (axis) {
var ticks = [];
......@@ -1252,7 +1250,7 @@
do {
prev = v;
v = start + i * axis.tickSize;
ticks.push({ v: v, label: axis.tickFormatter(v, axis) });
ticks.push(v);
++i;
} while (v < axis.max && v != prev);
return ticks;
......@@ -1263,7 +1261,44 @@
};
}
axis.tickSize = unit ? [size, unit] : size;
if (opts.alignTicksWithAxis != null) {
var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];
if (otherAxis && otherAxis.used && otherAxis != axis) {
// consider snapping min/max to outermost nice ticks
var niceTicks = generator(axis);
if (niceTicks.length > 0) {
if (opts.min == null)
axis.min = Math.min(axis.min, niceTicks[0]);
if (opts.max == null && niceTicks.length > 1)
axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);
}
generator = function (axis) {
// copy ticks, scaled to this axis
var ticks = [], v, i;
for (i = 0; i < otherAxis.ticks.length; ++i) {
v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);
v = axis.min + v * (axis.max - axis.min);
ticks.push(v);
}
return ticks;
};
// we might need an extra decimal since forced
// ticks don't necessarily fit naturally
if (axis.mode != "time" && opts.tickDecimals == null) {
var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1),
ts = generator(axis);
// only proceed if the tick interval rounded
// with an extra decimal doesn't give us a
// zero at end
if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))
axis.tickDecimals = extraDec;
}
}
}
axis.tickGenerator = generator;
if ($.isFunction(opts.tickFormatter))
axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };
......@@ -1272,24 +1307,20 @@
}
function setTicks(axis) {
var opts = axis.options;
axis.ticks = [];
if (opts.ticks == null)
axis.ticks = axis.tickGenerator(axis);
else if (typeof opts.ticks == "number") {
if (opts.ticks > 0)
axis.ticks = axis.tickGenerator(axis);
}
else if (opts.ticks) {
var ticks = opts.ticks;
if ($.isFunction(ticks))
var oticks = axis.options.ticks, ticks = null;
if (oticks == null || (typeof oticks == "number" && oticks > 0))
ticks = axis.tickGenerator(axis);
else if (oticks) {
if ($.isFunction(oticks))
// generate the ticks
ticks = ticks({ min: axis.min, max: axis.max });
ticks = oticks({ min: axis.min, max: axis.max });
else
ticks = oticks;
}
// clean up the user-supplied ticks, copy them over
// clean up/labelify the supplied ticks, copy them over
var i, v;
for (i = 0; i < ticks.length; ++i) {
var label = null;
......@@ -1307,12 +1338,13 @@
}
}
if (opts.autoscaleMargin != null && axis.ticks.length > 0) {
function snapRangeToTicks(axis, ticks) {
if (axis.options.autoscaleMargin != null && ticks.length > 0) {
// snap to ticks
if (opts.min == null)
axis.min = Math.min(axis.min, axis.ticks[0].v);
if (opts.max == null && axis.ticks.length > 1)
axis.max = Math.max(axis.max, axis.ticks[axis.ticks.length - 1].v);
if (axis.options.min == null)
axis.min = Math.min(axis.min, ticks[0].v);
if (axis.options.max == null && ticks.length > 1)
axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);
}
}
......
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