Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
F
flot
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
HS-public
flot
Commits
4318eeae
Commit
4318eeae
authored
Jul 15, 2013
by
David Schnur
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1090 from dnschnur/axis-labels
Added axis labels and rotated text support.
parents
b079efca
4d1042ab
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
431 additions
and
239 deletions
+431
-239
API.md
API.md
+116
-118
jquery.flot.js
jquery.flot.js
+315
-121
No files found.
API.md
View file @
4318eeae
...
...
@@ -245,60 +245,63 @@ xaxis, yaxis: {
show
:
null
or
true
/
false
position
:
"bottom"
or
"top"
or
"left"
or
"right"
mode
:
null
or
"time"
(
"time"
requires
jquery
.
flot
.
time
.
js
plugin
)
timezone
:
null
,
"browser"
or
timezone
(
only
makes
sense
for
mode
:
"time"
)
timezone
:
null
or
"browser"
or
timezone
(
only
used
with
mode
:
"time"
)
color
:
null
or
color
spec
tickColor
:
null
or
color
spec
font
:
null
or
font
spec
object
font
:
null
or
font
-
options
object
min
:
null
or
number
max
:
null
or
number
autoscaleMargin
:
null
or
number
transform
:
null
or
fn
:
number
->
number
inverseTransform
:
null
or
fn
:
number
->
number
ticks
:
null
or
number
or
ticks
array
or
(
fn
:
axis
->
ticks
array
)
tickSize
:
number
or
array
minTickSize
:
number
or
array
tickFormatter
:
(
fn
:
number
,
object
->
string
)
or
string
tickDecimals
:
null
or
number
tickFormatter
:
(
fn
:
number
,
object
->
string
)
or
string
labelWidth
:
null
or
number
labelHeight
:
null
or
number
reserveSpace
:
null
or
true
tickColor
:
null
or
color
spec
tickLength
:
null
or
number
tickWidth
:
null
or
number
tickHeight
:
null
or
number
tickFont
:
null
or
font
-
options
object
label
:
null
or
string
labelFont
:
null
or
font
spec
object
labelPadding
:
null
or
number
alignTicksWithAxis
:
null
or
number
reserveSpace
:
null
or
true
}
```
All axes have the same kind of options. The following describes how to
configure one axis, see below for what to do if you've got more than
one x axis or y axis.
All axes share the same set of options. The following descriptions are for a
single axis; read further down for how to create multiple x-axes or y-axes.
If you don't set the "show" option (i.e. it is null), visibility is
auto-detected, i.e. the axis will show up if there's data associated
with it. You can override this by setting the "show" option to true or
false.
The "position" option specifies where the axis is placed, bottom or
top for x axes, left or right for y axes. The "mode" option determines
how the data is interpreted, the default of null means as decimal
numbers. Use "time" for time series data; see the time series data
section. The time plugin (jquery.flot.time.js) is required for time
series support.
The "color" option determines the color of the line and ticks for the axis, and
defaults to the grid color with transparency. For more fine-grained control you
can also set the color of the ticks separately with "tickColor".
You can customize the font and color used to draw the axis tick labels with CSS
or directly via the "font" option. When "font" is null - the default - each
tick label is given the 'flot-tick-label' class. For compatibility with Flot
0.
7 and earlier the labels are also given the 'tickLabel' class, but this is
deprecated and scheduled to be removed with the release of version 1.0.0.
auto-detected, i.e. the axis will show up only if there's data associated
with it. You can override this by setting "show" to true or false.
The "position" option specifies where the axis is placed; bottom or top for x
axes, and left or right for y axes.
The "mode" option determines how the data is interpreted, the default of null
interprets it as decimal numbers, while "time" interprets it as time series
data. See the time series data section for more information, and note that
the time plugin (jquery.flot.time.js) is required for time series support.
The "color" option determines the color of the axis line and defaults for the
tick markers and label text. It defaults to the grid color with transparency.
You can customize the font and color used to draw axis text with CSS or via
the "font" option. When "font" is null (the default) tick labels are assigned
the 'flot-tick-label' class. For compatibility with Flot 0.7 and earlier the
labels are also assigned the 'tickLabel' class, but this is deprecated and
scheduled to be removed with the release of version 1.0.0.
To enable more granular control over styles, labels are divided between a set
of text containers, with each holding the labels for one axis. These containers
...
...
@@ -313,7 +316,7 @@ labels for a simple plot with only a single x-axis might look like this:
</div>
```
For direct control over
label
styles you can also provide "font" as an object
For direct control over
text
styles you can also provide "font" as an object
with this format:
```
js
...
...
@@ -331,28 +334,25 @@ with this format:
The size and lineHeight must be expressed in pixels; CSS units such as 'em'
or 'smaller' are not allowed.
The options "min"/"max" are the precise minimum/maximum value on the
scale. If you don't specify either of them, a value will automatically
be chosen based on the minimum/maximum data values. Note that Flot
always examines all the data values you feed to it, even if a
restriction on another axis may make some of them invisible (this
makes interactive use more stable).
The "autoscaleMargin" is a bit esoteric: it's the fraction of margin
that the scaling algorithm will add to avoid that the outermost points
ends up on the grid border. Note that this margin is only applied when
a min or max value is not explicitly set. If a margin is specified,
the plot will furthermore extend the axis end-point to the nearest
whole tick. The default value is "null" for the x axes and 0.02 for y
axes which seems appropriate for most cases.
"transform" and "inverseTransform" are callbacks you can put in to
change the way the data is drawn. You can design a function to
compress or expand certain parts of the axis non-linearly, e.g.
suppress weekends or compress far away points with a logarithm or some
other means. When Flot draws the plot, each value is first put through
the transform function. Here's an example, the x axis can be turned
into a natural logarithm axis with the following code:
The "min" and "max" options specify the precise minimum/maximum value on the
scale. If you don't specify either of them, Flot will automatically choose a
value based on the min/max values in the data. Note that Flot always examines
all the data values you feed to it, even if a restriction on another axis may
make some of them invisible (this makes interactive use more stable).
The "autoscaleMargin" option is a bit esoteric: it's the fraction of margin
that the scaling algorithm will add to avoid having the outermost points end
up on the grid border. Note that this margin is only applied when a min or
max value is not explicitly set. If a margin is specified, the plot will also
extend the axis end-point to the nearest whole tick. The default value is null
for the x-axes and 0.02 for y-axes; this seems appropriate for most cases.
"transform" and "inverseTransform" are callbacks that you can use to change
how the data is drawn. You can design a function to compress or expand parts
of the axis non-linearly, e.g. suppress weekends or compress far-away points
with a logarithm or some other means. When Flot draws the plot, each value is
first put through the transform function. For example, this is how one would
implement a log scale on the x-axis:
```
js
xaxis
:
{
...
...
@@ -361,8 +361,7 @@ xaxis: {
}
```
Similarly, for reversing the y axis so the values appear in inverse
order:
Similarly, for reversing the y axis so the values appear in inverse order:
```
js
yaxis
:
{
...
...
@@ -371,38 +370,34 @@ yaxis: {
}
```
Note that for finding extrema, Flot assumes that the transform
function does not reorder values (it should be monotone).
The inverseTransform is simply the inverse of the transform function
(so v == inverseTransform(transform(v)) for all relevant v). It is
required for converting from canvas coordinates to data coordinates,
e.g. for a mouse interaction where a certain pixel is clicked. If you
don't use any interactive features of Flot, you may not need it.
Note that for finding extrema, Flot assumes that the transform function does
not reorder values (it should be monotone).
The inverseTransform is simply the inverse of the transform function, so
v == inverseTransform(transform(v)) for all relevant v. It is required for
converting from canvas coordinates to data coordinates, i.e. for a mouse
interaction where a certain pixel is clicked. If you don't use any
interactive features of Flot, you may not need it.
The rest of the options deal with the ticks.
If you don't specify any ticks options, a tick generator algorithm will make
some for you. The algorithm has two passes. It first estimates how many ticks
would be reasonable, uses this to compute a nice round tick interval size,
then generates the ticks.
If you don't specify any ticks, a tick generator algorithm will make
some for you. The algorithm has two passes. It first estimates how
many ticks would be reasonable and uses this number to compute a nice
round tick interval size. Then it generates the ticks.
You can specify how many ticks the algorithm aims for by setting "ticks" to a
number. The algorithm always tries to generate reasonably round tick values
so even if you ask for three ticks, you might get five if that fits better
with the rounding. If you don't want any ticks at all, set "ticks" to 0 or an
empty array.
You can specify how many ticks the algorithm aims for by setting
"ticks" to a number. The algorithm always tries to generate reasonably
round tick values so even if you ask for three ticks, you might get
five if that fits better with the rounding. If you don't want any
ticks at all, set "ticks" to 0 or an empty array
.
Another option is to skip the rounding and directly set the tick interval
with "tickSize". Setting it to 2 gives you ticks at 2, 4, 6, etc. You can
also specify that you just don't want ticks at a size less than a specific
tick size with "minTickSize". Note that for time series, the format is an
array like
[
2, "month"
]
; see the time series data section for more info
.
Another option is to skip the rounding part and directly set the tick
interval size with "tickSize". If you set it to 2, you'll get ticks at
2, 4, 6, etc. Alternatively, you can specify that you just don't want
ticks at a size less than a specific tick size with "minTickSize".
Note that for time series, the format is an array like
[
2, "month"
]
,
see the next section.
If you want to completely override the tick algorithm, you can specify
an array for "ticks", either like this:
If you want to completely override the tick algorithm, you can specify an
array for "ticks", either like this:
```
js
ticks
:
[
0
,
1.2
,
2.4
]
...
...
@@ -416,11 +411,10 @@ ticks: [[0, "zero"], [1.2, "one mark"], [2.4, "two marks"]]
You can mix the two if you like.
For extra flexibility you can specify a function as the "ticks"
parameter. The function will be called with an object with the axis
min and max and should return a ticks array. Here's a simplistic tick
generator that spits out intervals of pi, suitable for use on the x
axis for trigonometric functions:
For extra flexibility you can specify a function as the "ticks" parameter.
The function will be called with an object with the axis min and max, and
should return a ticks array. Here's a simple tick generator that produces
intervals of pi, suitable for use on the x-axis for trigonometric functions:
```
js
function
piTickGenerator
(
axis
)
{
...
...
@@ -434,13 +428,13 @@ function piTickGenerator(axis) {
}
```
You can control how the ticks look
like with "tickDecimals",
the
You can control how the ticks look
with "tickDecimals", which specifies
the
number of decimals to display (default is auto-detected).
Alternatively, for ultimate control over how ticks are formatted you can
provide a function to "tickFormatter". The function is passed two
parameters, the tick value and an axis object with information, and
s
hould return a s
tring. The default formatter looks like this:
provide a function to "tickFormatter". The function is passed two
parameters,
the tick value and an axis object with information, and should return a
string. The default formatter looks like this:
```
js
function
formatter
(
val
,
axis
)
{
...
...
@@ -448,11 +442,10 @@ function formatter(val, axis) {
}
```
The axis object has "min" and "max" with the range of the axis,
"tickDecimals" with the number of decimals to round the value to and
"tickSize" with the size of the interval between ticks as calculated
by the automatic axis scaling algorithm (or specified by you). Here's
an example of a custom formatter:
The axis object has "min" and "max" with the axis range, "tickDecimals" with
the number of decimals to round the value to and "tickSize" with the size of
the interval between ticks as calculated by the automatic axis scaling
algorithm (or specified by you). Here's an example of a custom formatter:
```
js
function
suffixFormatter
(
val
,
axis
)
{
...
...
@@ -465,25 +458,30 @@ function suffixFormatter(val, axis) {
}
```
"labelWidth" and "labelHeight" specifies a fixed size of the tick
labels in pixels. They're useful in case you need to align several
plots. "reserveSpace" means that even if an axis isn't shown, Flot
should reserve space for it - it is useful in combination with
labelWidth and labelHeight for aligning multi-axis charts.
"tickLength" is the length of the tick lines in pixels. By default, the
innermost axes will have ticks that extend all across the plot, while
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.
"tickLength" is the length of the tick marks in pixels. By default the
innermost axes have ticks that extend across the plot, while any extra axes
use small ticks. A value of null means to use the default, while a number
means to use ticks of that length, where zero hides the marks completely.
You can use "tickColor" to override the "color" option and give the tick
marks a different color from the axis line itself.
"tickWidth" and "tickHeight" specify a fixed size for the tick labels, in
pixels. They're useful in case you need to assign several plots.
You can use "tickFont" to give tick labels a different font style from the
axis default. It accepts exactly the same font-options object as "font" does.
When using multiple axes, if you set "alignTicksWithAxis" to the number of
another axis, e.g. alignTicksWithAxis: 1, Flot will ensure that the generated
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 on both ends. The
trade-off is that the forced ticks won't necessarily be at natural places.
"reserveSpace" indicates that Flot should reserve space for the axis even if
it isn't visible. This is useful in combination with labelWidth/labelHeight
for aligning multi-axis charts.
## Multiple axes ##
...
...
jquery.flot.js
View file @
4318eeae
...
...
@@ -151,28 +151,33 @@ Licensed under the MIT license.
for
(
var
styleKey
in
layerCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
layerCache
,
styleKey
))
{
var
styleCache
=
layerCache
[
styleKey
];
for
(
var
key
in
styleCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
styleCache
,
key
))
{
var
positions
=
styleCache
[
key
].
positions
;
for
(
var
i
=
0
,
position
;
position
=
positions
[
i
];
i
++
)
{
if
(
position
.
active
)
{
if
(
!
position
.
rendered
)
{
layer
.
append
(
position
.
element
);
position
.
rendered
=
true
;
}
}
else
{
positions
.
splice
(
i
--
,
1
);
if
(
position
.
rendered
)
{
position
.
element
.
detach
();
}
}
}
if
(
positions
.
length
===
0
)
{
delete
styleCache
[
key
];
}
for
(
var
angleKey
in
styleCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
styleCache
,
angleKey
))
{
var
angleCache
=
styleCache
[
angleKey
];
for
(
var
key
in
angleCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
angleCache
,
key
))
{
var
positions
=
angleCache
[
key
].
positions
;
for
(
var
i
=
0
,
position
;
position
=
positions
[
i
];
i
++
)
{
if
(
position
.
active
)
{
if
(
!
position
.
rendered
)
{
layer
.
append
(
position
.
element
);
position
.
rendered
=
true
;
}
}
else
{
positions
.
splice
(
i
--
,
1
);
if
(
position
.
rendered
)
{
position
.
element
.
detach
();
}
}
}
if
(
positions
.
length
===
0
)
{
delete
angleCache
[
key
];
}
}
}
}
}
}
...
...
@@ -264,17 +269,15 @@ Licensed under the MIT license.
// @param {(string|object)=} font Either a string of space-separated CSS
// classes or a font-spec object, defining the text's font and style.
// @param {number=} angle Angle at which to rotate the text, in degrees.
// Angle is currently unused, it will be implemented in the future.
// @param {number=} width Maximum width of the text before it wraps.
// @return {object} a text info object.
Canvas
.
prototype
.
getTextInfo
=
function
(
layer
,
text
,
font
,
angle
,
width
)
{
var
textStyle
,
layerCache
,
sty
leCache
,
info
;
var
textStyle
,
layerCache
,
styleCache
,
ang
leCache
,
info
;
// Cast the value to a string, in case we were given a number or such
text
=
""
+
text
;
text
=
""
+
text
;
// Cast to string in case we have a number or such
angle
=
(
360
+
(
angle
||
0
))
%
360
;
// Normalize the angle to 0...359
// If the font is a font-spec object, generate a CSS font definition
...
...
@@ -284,21 +287,24 @@ Licensed under the MIT license.
textStyle
=
font
;
}
// Retrieve (or create) the cache for the text's layer and styles
// Retrieve or create the caches for the text's layer, style, and angle
layerCache
=
this
.
_textCache
[
layer
];
if
(
layerCache
==
null
)
{
layerCache
=
this
.
_textCache
[
layer
]
=
{};
}
styleCache
=
layerCache
[
textStyle
];
if
(
styleCache
==
null
)
{
styleCache
=
layerCache
[
textStyle
]
=
{};
}
info
=
styleCache
[
text
];
angleCache
=
styleCache
[
angle
];
if
(
angleCache
==
null
)
{
angleCache
=
styleCache
[
angle
]
=
{};
}
info
=
angleCache
[
text
];
// If we can't find a matching element in our cache, create a new one
...
...
@@ -321,9 +327,117 @@ Licensed under the MIT license.
element
.
addClass
(
font
);
}
info
=
styleCache
[
text
]
=
{
width
:
element
.
outerWidth
(
true
),
height
:
element
.
outerHeight
(
true
),
// Save the original dimensions of the text; we'll modify these
// later to take into account rotation, if there is any.
var
textWidth
=
element
.
outerWidth
(
true
),
textHeight
=
element
.
outerHeight
(
true
);
// Apply rotation to the text using CSS3/IE matrix transforms
// Note how we also set the element's width, as a work-around for
// the way most browsers resize the div on rotate, which may cause
// the contents to wrap differently. The extra +1 is because IE
// rounds the width differently and needs a little extra help.
if
(
angle
)
{
var
radians
=
angle
*
Math
.
PI
/
180
,
sin
=
Math
.
sin
(
radians
),
cos
=
Math
.
cos
(
radians
),
a
=
cos
.
toFixed
(
6
),
// Use fixed-point so these don't
b
=
(
-
sin
).
toFixed
(
6
),
// show up in scientific notation
c
=
sin
.
toFixed
(
6
),
// when we add them to the string
transformRule
;
if
(
$
.
support
.
leadingWhitespace
)
{
// The transform origin defaults to '50% 50%', producing
// blurry text on some browsers (Chrome) when the width or
// height happens to be odd, making 50% fractional. Avoid
// this by setting the origin to rounded values.
var
cx
=
textWidth
/
2
,
cy
=
textHeight
/
2
,
transformOrigin
=
Math
.
floor
(
cx
)
+
"px "
+
Math
.
floor
(
cy
)
+
"px"
;
// Transforms alter the div's appearance without changing
// its origin. This will make it difficult to position it
// later, since we'll be positioning the new bounding box
// with respect to the old origin. We can work around this
// by adding a translation to align the new bounding box's
// top-left corner with the origin, using the same matrix.
// Rather than examining all four points, we can use the
// angle to figure out in advance which two points are in
// the top-left quadrant; we can then use the x-coordinate
// of the first (left-most) point and the y-coordinate of
// the second (top-most) point as the bounding box corner.
var
x
,
y
;
if
(
angle
<
90
)
{
x
=
Math
.
floor
(
cx
*
cos
+
cy
*
sin
-
cx
);
y
=
Math
.
floor
(
cx
*
sin
+
cy
*
cos
-
cy
);
}
else
if
(
angle
<
180
)
{
x
=
Math
.
floor
(
cy
*
sin
-
cx
*
cos
-
cx
);
y
=
Math
.
floor
(
cx
*
sin
-
cy
*
cos
-
cy
);
}
else
if
(
angle
<
270
)
{
x
=
Math
.
floor
(
-
cx
*
cos
-
cy
*
sin
-
cx
);
y
=
Math
.
floor
(
-
cx
*
sin
-
cy
*
cos
-
cy
);
}
else
{
x
=
Math
.
floor
(
cx
*
cos
-
cy
*
sin
-
cx
);
y
=
Math
.
floor
(
cy
*
cos
-
cx
*
sin
-
cy
);
}
transformRule
=
"matrix("
+
a
+
","
+
c
+
","
+
b
+
","
+
a
+
","
+
x
+
","
+
y
+
")"
;
element
.
css
({
width
:
textWidth
+
1
,
transform
:
transformRule
,
"-o-transform"
:
transformRule
,
"-ms-transform"
:
transformRule
,
"-moz-transform"
:
transformRule
,
"-webkit-transform"
:
transformRule
,
"transform-origin"
:
transformOrigin
,
"-o-transform-origin"
:
transformOrigin
,
"-ms-transform-origin"
:
transformOrigin
,
"-moz-transform-origin"
:
transformOrigin
,
"-webkit-transform-origin"
:
transformOrigin
});
}
else
{
// The IE7/8 matrix filter produces very ugly aliasing for
// text with a transparent background. Using a solid color
// greatly improves text clarity, although it does result
// in ugly boxes for plots using a non-white background.
// TODO: Instead of white use the actual background color?
// This still wouldn't solve the problem when the plot has
// a gradient background, but it would at least help.
transformRule
=
"progid:DXImageTransform.Microsoft.Matrix(M11="
+
a
+
", M12="
+
b
+
", M21="
+
c
+
", M22="
+
a
+
",sizingMethod='auto expand')"
;
element
.
css
({
width
:
textWidth
+
1
,
filter
:
transformRule
,
"-ms-filter"
:
transformRule
,
"background-color"
:
"#fff"
});
}
// Compute the final dimensions of the text's bounding box
var
ac
=
Math
.
abs
(
cos
),
as
=
Math
.
abs
(
sin
),
originalWidth
=
textWidth
;
textWidth
=
Math
.
round
(
ac
*
textWidth
+
as
*
textHeight
);
textHeight
=
Math
.
round
(
as
*
originalWidth
+
ac
*
textHeight
);
}
info
=
angleCache
[
text
]
=
{
width
:
textWidth
,
height
:
textHeight
,
element
:
element
,
positions
:
[]
};
...
...
@@ -347,7 +461,6 @@ Licensed under the MIT license.
// @param {(string|object)=} font Either a string of space-separated CSS
// classes or a font-spec object, defining the text's font and style.
// @param {number=} angle Angle at which to rotate the text, in degrees.
// Angle is currently unused, it will be implemented in the future.
// @param {number=} width Maximum width of the text before it wraps.
// @param {string=} halign Horizontal alignment of the text; either "left",
// "center" or "right".
...
...
@@ -435,14 +548,19 @@ Licensed under the MIT license.
for
(
var
styleKey
in
layerCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
layerCache
,
styleKey
))
{
var
styleCache
=
layerCache
[
styleKey
];
for
(
var
key
in
styleCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
styleCache
,
key
))
{
positions
=
styleCache
[
key
].
positions
;
for
(
i
=
0
;
position
=
positions
[
i
];
i
++
)
{
position
.
active
=
false
;
}
}
}
for
(
var
angleKey
in
styleCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
styleCache
,
angleKey
))
{
var
angleCache
=
styleCache
[
angleKey
];
for
(
var
key
in
angleCache
)
{
if
(
Object
.
prototype
.
hasOwnProperty
.
call
(
angleCache
,
key
))
{
positions
=
angleCache
[
key
].
positions
;
for
(
i
=
0
;
position
=
positions
[
i
];
i
++
)
{
position
.
active
=
false
;
}
}
}
}
}
}
}
}
...
...
@@ -482,31 +600,45 @@ Licensed under the MIT license.
sorted
:
null
// default to no legend sorting
},
xaxis
:
{
show
:
null
,
// null = auto-detect, true = always, false = never
position
:
"bottom"
,
// or "top"
mode
:
null
,
// null or "time"
font
:
null
,
// null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }
color
:
null
,
// base color, labels, ticks
tickColor
:
null
,
// possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
transform
:
null
,
// null or f: number -> number to transform axis
show
:
null
,
// null = auto-detect, true = always, false = never
position
:
"bottom"
,
// or "top"
mode
:
null
,
// null or "time"
color
:
null
,
// base color, labels, ticks
font
:
null
,
// null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }
min
:
null
,
// min. value to show, null means set automatically
max
:
null
,
// max. value to show, null means set automatically
autoscaleMargin
:
null
,
// margin in % to add if auto-setting min/max
transform
:
null
,
// null or f: number -> number to transform axis
inverseTransform
:
null
,
// if transform is set, this should be the inverse function
min
:
null
,
// min. value to show, null means set automatically
max
:
null
,
// max. value to show, null means set automatically
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
labelWidth
:
null
,
// size of tick labels in pixels
labelHeight
:
null
,
reserveSpace
:
null
,
// whether to reserve space even if axis isn't shown
tickLength
:
null
,
// size in pixels of ticks, or "full" for whole line
alignTicksWithAxis
:
null
,
// axis number or null for no sync
tickDecimals
:
null
,
// no. of decimals, null means auto
tickSize
:
null
,
// number or [number, "unit"]
minTickSize
:
null
// number or [number, "unit"]
ticks
:
null
,
// either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks
tickSize
:
null
,
// number or [number, "unit"]
minTickSize
:
null
,
// number or [number, "unit"]
tickFormatter
:
null
,
// fn: number -> string
tickDecimals
:
null
,
// no. of decimals, null means auto
tickColor
:
null
,
// possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
tickLength
:
null
,
// size in pixels of ticks, or "full" for whole line
tickWidth
:
null
,
// width of tick labels in pixels
tickHeight
:
null
,
// height of tick labels in pixels
tickFont
:
null
,
// null or font-spec object (see font, above)
label
:
null
,
// null or an axis label string
labelFont
:
null
,
// null or font-spec object (see font, above)
labelPadding
:
2
,
// spacing between the axis and its label
reserveSpace
:
null
,
// whether to reserve space even if axis isn't shown
alignTicksWithAxis
:
null
// axis number or null for no sync
},
yaxis
:
{
position
:
"left"
,
// or "right"
autoscaleMargin
:
0.02
,
position
:
"left"
// or "right"
labelPadding
:
2
},
xaxes
:
[],
yaxes
:
[],
...
...
@@ -733,14 +865,27 @@ Licensed under the MIT license.
axisOptions
.
tickColor
=
axisOptions
.
color
;
}
// Compatibility with markrcote/flot-axislabels
if
(
!
axisOptions
.
label
&&
axisOptions
.
axisLabel
)
{
axisOptions
.
label
=
axisOptions
.
axisLabel
;
}
if
(
!
axisOptions
.
labelPadding
&&
axisOptions
.
axisLabelPadding
)
{
axisOptions
.
labelPadding
=
axisOptions
.
axisLabelPadding
;
}
axisOptions
=
$
.
extend
(
true
,
{},
options
.
xaxis
,
axisOptions
);
options
.
xaxes
[
i
]
=
axisOptions
;
fontDefaults
.
color
=
axisOptions
.
color
;
if
(
axisOptions
.
font
)
{
axisOptions
.
font
=
$
.
extend
({},
fontDefaults
,
axisOptions
.
font
);
if
(
!
axisOptions
.
font
.
color
)
{
axisOptions
.
font
.
color
=
axisOptions
.
color
;
}
}
if
(
axisOptions
.
tickFont
||
axisOptions
.
font
)
{
axisOptions
.
tickFont
=
$
.
extend
({},
axisOptions
.
font
||
fontDefaults
,
axisOptions
.
tickFont
);
}
if
(
axisOptions
.
label
&&
(
axisOptions
.
labelFont
||
axisOptions
.
font
))
{
axisOptions
.
labelFont
=
$
.
extend
({},
axisOptions
.
font
||
fontDefaults
,
axisOptions
.
labelFont
);
}
}
...
...
@@ -752,14 +897,27 @@ Licensed under the MIT license.
axisOptions
.
tickColor
=
axisOptions
.
color
;
}
// Compatibility with markrcote/flot-axislabels
if
(
!
axisOptions
.
label
&&
axisOptions
.
axisLabel
)
{
axisOptions
.
label
=
axisOptions
.
axisLabel
;
}
if
(
!
axisOptions
.
labelPadding
&&
axisOptions
.
axisLabelPadding
)
{
axisOptions
.
labelPadding
=
axisOptions
.
axisLabelPadding
;
}
axisOptions
=
$
.
extend
(
true
,
{},
options
.
yaxis
,
axisOptions
);
options
.
yaxes
[
i
]
=
axisOptions
;
fontDefaults
.
color
=
axisOptions
.
color
;
if
(
axisOptions
.
font
)
{
axisOptions
.
font
=
$
.
extend
({},
fontDefaults
,
axisOptions
.
font
);
if
(
!
axisOptions
.
font
.
color
)
{
axisOptions
.
font
.
color
=
axisOptions
.
color
;
}
}
if
(
axisOptions
.
tickFont
||
axisOptions
.
font
)
{
axisOptions
.
tickFont
=
$
.
extend
({},
axisOptions
.
font
||
fontDefaults
,
axisOptions
.
tickFont
);
}
if
(
axisOptions
.
label
&&
(
axisOptions
.
labelFont
||
axisOptions
.
font
))
{
axisOptions
.
labelFont
=
$
.
extend
({},
axisOptions
.
font
||
fontDefaults
,
axisOptions
.
labelFont
);
}
}
...
...
@@ -1370,12 +1528,12 @@ Licensed under the MIT license.
var
opts
=
axis
.
options
,
ticks
=
axis
.
ticks
||
[],
labelWidth
=
opts
.
labelWidth
||
0
,
labelHeight
=
opts
.
labelHeight
||
0
,
maxWidth
=
labelWidth
||
axis
.
direction
===
"x"
?
Math
.
floor
(
surface
.
width
/
(
ticks
.
length
||
1
))
:
null
,
legacyStyles
=
axis
.
direction
+
"Axis "
+
axis
.
direction
+
axis
.
n
+
"Axis"
,
layer
=
"flot-"
+
axis
.
direction
+
"-axis flot-"
+
axis
.
direction
+
axis
.
n
+
"-axis "
+
legacyStyles
,
font
=
opts
.
f
ont
||
"flot-tick-label tickLabel"
;
// Label width & height are deprecated; remove in 1.0!
tickWidth
=
opts
.
tickWidth
||
opts
.
labelWidth
||
0
,
tickHeight
=
opts
.
tickHeight
||
opts
.
labelHeight
||
0
,
maxWidth
=
tickWidth
||
axis
.
direction
===
"x"
?
Math
.
floor
(
surface
.
width
/
(
ticks
.
length
||
1
))
:
null
,
layer
=
"flot-"
+
axis
.
direction
+
"-axis flot-"
+
axis
.
direction
+
axis
.
n
+
"-axis "
+
axis
.
direction
+
"Axis "
+
axis
.
direction
+
axis
.
n
+
"Axis"
,
font
=
opts
.
tickF
ont
||
"flot-tick-label tickLabel"
;
for
(
var
i
=
0
;
i
<
ticks
.
length
;
++
i
)
{
...
...
@@ -1387,33 +1545,42 @@ Licensed under the MIT license.
var
info
=
surface
.
getTextInfo
(
layer
,
t
.
label
,
font
,
null
,
maxWidth
);
labelWidth
=
Math
.
max
(
label
Width
,
info
.
width
);
labelHeight
=
Math
.
max
(
label
Height
,
info
.
height
);
tickWidth
=
Math
.
max
(
tick
Width
,
info
.
width
);
tickHeight
=
Math
.
max
(
tick
Height
,
info
.
height
);
}
axis
.
labelWidth
=
opts
.
labelWidth
||
labelWidth
;
axis
.
labelHeight
=
opts
.
labelHeight
||
labelHeight
;
axis
.
tickWidth
=
opts
.
tickWidth
||
opts
.
labelWidth
||
tickWidth
;
axis
.
tickHeight
=
opts
.
tickHeight
||
opts
.
labelHeight
||
tickHeight
;
// Label width/height properties are deprecated; remove in 1.0!
axis
.
labelWidth
=
axis
.
tickWidth
;
axis
.
labelHeight
=
axis
.
tickHeight
;
}
///////////////////////////////////////////////////////////////////////
// Compute the axis bounding box based on the dimensions of its label
// and tick labels, then adjust the plotOffset to make room for it.
//
// This first phase only considers one dimension per axis; the other
// dimension depends on the other axes, and will be calculated later.
function
allocateAxisBoxFirstPhase
(
axis
)
{
// find the bounding box of the axis by looking at label
// widths/heights and ticks, make room by diminishing the
// plotOffset; this first phase only looks at one
// dimension per axis, the other dimension depends on the
// other axes so will have to wait
var
lw
=
axis
.
labelWidth
,
lh
=
axis
.
labelHeight
,
pos
=
axis
.
options
.
position
,
tickLength
=
axis
.
options
.
tickLength
,
var
contentWidth
=
axis
.
tickWidth
,
contentHeight
=
axis
.
tickHeight
,
axisOptions
=
axis
.
options
,
tickLength
=
axisOptions
.
tickLength
,
axisPosition
=
axisOptions
.
position
,
axisMargin
=
options
.
grid
.
axisMargin
,
padding
=
options
.
grid
.
labelMargin
,
all
=
axis
.
direction
===
"x"
?
xaxes
:
yaxes
,
innermost
;
// determine axis margin
var
samePosition
=
$
.
grep
(
all
,
function
(
a
)
{
return
a
&&
a
.
options
.
position
===
pos
&&
a
.
reserveSpace
;
// Determine the margin around the axis
var
samePosition
=
$
.
grep
(
all
,
function
(
axis
)
{
return
axis
&&
axis
.
options
.
position
===
axisPosition
&&
axis
.
reserveSpace
;
});
if
(
$
.
inArray
(
axis
,
samePosition
)
===
samePosition
.
length
-
1
)
{
axisMargin
=
0
;
// outermost
...
...
@@ -1423,7 +1590,7 @@ Licensed under the MIT license.
innermost
=
$
.
inArray
(
axis
,
samePosition
)
===
0
;
//
determine tick length - if we're innermost, we can use "full"
//
Determine the length of the tick marks
if
(
tickLength
==
null
)
{
if
(
innermost
)
{
...
...
@@ -1437,31 +1604,40 @@ Licensed under the MIT license.
padding
+=
+
tickLength
;
}
// compute box
if
(
axis
.
direction
===
"x"
)
{
lh
+=
padding
;
// Measure the dimensions of the axis label, if it has one
if
(
axisOptions
.
label
)
{
var
layer
=
"flot-"
+
axis
.
direction
+
"-axis flot-"
+
axis
.
direction
+
axis
.
n
+
"-axis "
+
axis
.
direction
+
"Axis "
+
axis
.
direction
+
axis
.
n
+
"Axis"
,
font
=
axisOptions
.
labelFont
||
"flot-axis-label axisLabels "
+
axis
.
direction
+
axis
.
n
+
"axisLabel"
,
angle
=
axis
.
direction
===
"x"
?
0
:
axisOptions
.
position
===
"right"
?
90
:
-
90
,
labelInfo
=
surface
.
getTextInfo
(
layer
,
axisOptions
.
label
,
font
,
angle
);
contentWidth
+=
labelInfo
.
width
+
axisOptions
.
labelPadding
;
contentHeight
+=
labelInfo
.
height
+
axisOptions
.
labelPadding
;
}
if
(
pos
===
"bottom"
)
{
plotOffset
.
bottom
+=
lh
+
axisMargin
;
axis
.
box
=
{
top
:
surface
.
height
-
plotOffset
.
bottom
,
height
:
lh
};
// Compute the axis bounding box and update the plot bounds
if
(
axis
.
direction
===
"x"
)
{
contentHeight
+=
padding
;
if
(
axisPosition
===
"top"
)
{
axis
.
box
=
{
top
:
plotOffset
.
top
+
axisMargin
,
height
:
contentHeight
};
plotOffset
.
top
+=
contentHeight
+
axisMargin
;
}
else
{
axis
.
box
=
{
top
:
plotOffset
.
top
+
axisMargin
,
height
:
lh
}
;
plotOffset
.
top
+=
lh
+
axisMargin
;
plotOffset
.
bottom
+=
contentHeight
+
axisMargin
;
axis
.
box
=
{
top
:
surface
.
height
-
plotOffset
.
bottom
,
height
:
contentHeight
}
;
}
}
else
{
lw
+=
padding
;
if
(
pos
===
"left"
)
{
axis
.
box
=
{
left
:
plotOffset
.
left
+
axisMargin
,
width
:
lw
};
plotOffset
.
left
+=
lw
+
axisMargin
;
contentWidth
+=
padding
;
if
(
axisPosition
===
"right"
)
{
plotOffset
.
right
+=
contentWidth
+
axisMargin
;
axis
.
box
=
{
left
:
surface
.
width
-
plotOffset
.
right
,
width
:
contentWidth
};
}
else
{
plotOffset
.
right
+=
lw
+
axisMargin
;
axis
.
box
=
{
left
:
surface
.
width
-
plotOffset
.
right
,
width
:
lw
}
;
axis
.
box
=
{
left
:
plotOffset
.
left
+
axisMargin
,
width
:
contentWidth
}
;
plotOffset
.
left
+=
contentWidth
+
axisMargin
;
}
}
// save for future reference
axis
.
position
=
pos
;
axis
.
position
=
axisPosition
;
axis
.
tickLength
=
tickLength
;
axis
.
box
.
padding
=
padding
;
axis
.
innermost
=
innermost
;
...
...
@@ -1471,11 +1647,11 @@ Licensed under the MIT license.
// now that all axis boxes have been placed in one
// dimension, we can set the remaining dimension coordinates
if
(
axis
.
direction
===
"x"
)
{
axis
.
box
.
left
=
plotOffset
.
left
-
axis
.
label
Width
/
2
;
axis
.
box
.
width
=
surface
.
width
-
plotOffset
.
left
-
plotOffset
.
right
+
axis
.
label
Width
;
axis
.
box
.
left
=
plotOffset
.
left
-
axis
.
tick
Width
/
2
;
axis
.
box
.
width
=
surface
.
width
-
plotOffset
.
left
-
plotOffset
.
right
+
axis
.
tick
Width
;
}
else
{
axis
.
box
.
top
=
plotOffset
.
top
-
axis
.
label
Height
/
2
;
axis
.
box
.
height
=
surface
.
height
-
plotOffset
.
bottom
-
plotOffset
.
top
+
axis
.
label
Height
;
axis
.
box
.
top
=
plotOffset
.
top
-
axis
.
tick
Height
/
2
;
axis
.
box
.
height
=
surface
.
height
-
plotOffset
.
bottom
-
plotOffset
.
top
+
axis
.
tick
Height
;
}
}
...
...
@@ -1504,7 +1680,7 @@ Licensed under the MIT license.
$
.
each
(
allAxes
(),
function
(
_
,
axis
)
{
var
dir
=
axis
.
direction
;
if
(
axis
.
reserveSpace
)
{
margins
[
dir
]
=
Math
.
ceil
(
Math
.
max
(
margins
[
dir
],
(
dir
===
"x"
?
axis
.
labelWidth
:
axis
.
label
Height
)
/
2
));
margins
[
dir
]
=
Math
.
ceil
(
Math
.
max
(
margins
[
dir
],
(
dir
===
"x"
?
axis
.
tickWidth
:
axis
.
tick
Height
)
/
2
));
}
});
...
...
@@ -1561,7 +1737,6 @@ Licensed under the MIT license.
setupTickGeneration
(
axis
);
setTicks
(
axis
);
snapRangeToTicks
(
axis
,
axis
.
ticks
);
// find labelWidth/Height for axis
measureTickLabels
(
axis
);
});
...
...
@@ -2160,13 +2335,32 @@ Licensed under the MIT license.
}
var
box
=
axis
.
box
,
legacyStyles
=
axis
.
direction
+
"Axis "
+
axis
.
direction
+
axis
.
n
+
"Axis"
,
layer
=
"flot-"
+
axis
.
direction
+
"-axis flot-"
+
axis
.
direction
+
axis
.
n
+
"-axis "
+
legacyStyles
,
font
=
axis
.
options
.
font
||
"flot-tick-label tickLabel"
,
axisOptions
=
axis
.
options
,
layer
=
"flot-"
+
axis
.
direction
+
"-axis flot-"
+
axis
.
direction
+
axis
.
n
+
"-axis "
+
axis
.
direction
+
"Axis "
+
axis
.
direction
+
axis
.
n
+
"Axis"
,
labelFont
=
axisOptions
.
labelFont
||
"flot-axis-label axisLabels "
+
axis
.
direction
+
axis
.
n
+
"axisLabel"
,
tickFont
=
axisOptions
.
tickFont
||
"flot-tick-label tickLabel"
,
tick
,
x
,
y
,
halign
,
valign
;
surface
.
removeText
(
layer
);
if
(
axisOptions
.
label
)
{
if
(
axis
.
direction
===
"x"
)
{
if
(
axisOptions
.
position
===
"top"
)
{
surface
.
addText
(
layer
,
box
.
left
+
box
.
width
/
2
,
box
.
top
,
axisOptions
.
label
,
labelFont
,
0
,
null
,
"center"
,
"top"
);
}
else
{
surface
.
addText
(
layer
,
box
.
left
+
box
.
width
/
2
,
box
.
top
+
box
.
height
,
axisOptions
.
label
,
labelFont
,
0
,
null
,
"center"
,
"bottom"
);
}
}
else
{
if
(
axisOptions
.
position
===
"right"
)
{
surface
.
addText
(
layer
,
box
.
left
+
box
.
width
,
box
.
top
+
box
.
height
/
2
,
axisOptions
.
label
,
labelFont
,
90
,
null
,
"right"
,
"middle"
);
}
else
{
surface
.
addText
(
layer
,
box
.
left
,
box
.
top
+
box
.
height
/
2
,
axisOptions
.
label
,
labelFont
,
-
90
,
null
,
"left"
,
"middle"
);
}
}
}
// Add labels for the ticks on this axis
for
(
var
i
=
0
;
i
<
axis
.
ticks
.
length
;
++
i
)
{
tick
=
axis
.
ticks
[
i
];
...
...
@@ -2194,7 +2388,7 @@ Licensed under the MIT license.
}
}
surface
.
addText
(
layer
,
x
,
y
,
tick
.
label
,
f
ont
,
null
,
null
,
halign
,
valign
);
surface
.
addText
(
layer
,
x
,
y
,
tick
.
label
,
tickF
ont
,
null
,
null
,
halign
,
valign
);
}
});
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment