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
89bbfef5
Commit
89bbfef5
authored
Apr 06, 2011
by
Ole Laursen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch to using canvas text to draw the axis labels, fix a problem with axis box calculations
parent
36df8f08
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
242 additions
and
188 deletions
+242
-188
API.txt
API.txt
+17
-3
FAQ.txt
FAQ.txt
+10
-10
NEWS.txt
NEWS.txt
+20
-2
interacting-axes.html
examples/interacting-axes.html
+5
-23
jquery.flot.js
jquery.flot.js
+190
-150
No files found.
API.txt
View file @
89bbfef5
...
@@ -178,7 +178,8 @@ Customizing the axes
...
@@ -178,7 +178,8 @@ Customizing the axes
color: null or color spec
color: null or color spec
tickColor: null or color spec
tickColor: null or color spec
font: null or font spec object
min: null or number
min: null or number
max: null or number
max: null or number
autoscaleMargin: null or number
autoscaleMargin: null or number
...
@@ -222,6 +223,20 @@ you can also set the color of the ticks separately with "tickColor"
...
@@ -222,6 +223,20 @@ you can also set the color of the ticks separately with "tickColor"
(otherwise it's autogenerated as the base color with some
(otherwise it's autogenerated as the base color with some
transparency).
transparency).
You can customize the font used to draw the labels with CSS or
directly with "font". The default value of null means that the font is
read from the font style on the placeholder element (80% the size of
that to be precise). If you set it directly with "font: { ... }", the
format is like this:
{
size: 11,
style: "italic",
weight: "bold",
family: "sans-serif",
variant: "small-caps"
}
The options "min"/"max" are the precise minimum/maximum value on the
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
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
be chosen based on the minimum/maximum data values. Note that Flot
...
@@ -677,8 +692,7 @@ above the data or below (below is default).
...
@@ -677,8 +692,7 @@ above the data or below (below is default).
"labelMargin" is the space in pixels between tick labels and axis
"labelMargin" is the space in pixels between tick labels and axis
line, and "axisMargin" is the space in pixels between axes when there
line, and "axisMargin" is the space in pixels between axes when there
are two next to each other. Note that you can style the tick labels
are two next to each other.
with CSS, e.g. to change the color. They have class "tickLabel".
"borderWidth" is the width of the border around the plot. Set it to 0
"borderWidth" is the width of the border around the plot. Set it to 0
to disable the border. You can also set "borderColor" if you want the
to disable the border. You can also set "borderColor" if you want the
...
...
FAQ.txt
View file @
89bbfef5
...
@@ -6,7 +6,8 @@ Q: How much data can Flot cope with?
...
@@ -6,7 +6,8 @@ Q: How much data can Flot cope with?
A: Flot will happily draw everything you send to it so the answer
A: Flot will happily draw everything you send to it so the answer
depends on the browser. The excanvas emulation used for IE (built with
depends on the browser. The excanvas emulation used for IE (built with
VML) makes IE by far the slowest browser so be sure to test with that
VML) makes IE by far the slowest browser so be sure to test with that
if IE users are in your target group.
if IE users are in your target group (for large plots in IE, you can
also check out Flashcanvas which may be faster).
1000 points is not a problem, but as soon as you start having more
1000 points is not a problem, but as soon as you start having more
points than the pixel width, you should probably start thinking about
points than the pixel width, you should probably start thinking about
...
@@ -25,10 +26,11 @@ conversion automatically.
...
@@ -25,10 +26,11 @@ conversion automatically.
Q: Can I export the graph?
Q: Can I export the graph?
A: This is a limitation of the canvas technology. There's a hook in
A: You can grab the image rendered by the canvas element used by Flot
the canvas object for getting an image out, but you won't get the tick
as a PNG or JPEG (remember to set a background). Note that it won't
labels. And it's not likely to be supported by IE. At this point, your
include anything not drawn in the canvas (such as the legend). And it
best bet is probably taking a screenshot, e.g. with PrtScn.
doesn't work with excanvas which uses VML, but you could try
Flashcanvas.
Q: The bars are all tiny in time mode?
Q: The bars are all tiny in time mode?
...
@@ -56,11 +58,9 @@ libraries") for details.
...
@@ -56,11 +58,9 @@ libraries") for details.
Q: Flot doesn't work with [insert name of Javascript UI framework]!
Q: Flot doesn't work with [insert name of Javascript UI framework]!
A: The only non-standard thing used by Flot is the canvas tag;
A: Flot is using standard HTML to make charts. If this is not working,
otherwise it is simply a series of absolute positioned divs within the
it's probably because the framework you're using is doing something
placeholder tag you put in. If this is not working, it's probably
weird with the DOM or with the CSS that is interfering with Flot.
because the framework you're using is doing something weird with the
DOM, or you're using it the wrong way.
A common problem is that there's display:none on a container until the
A common problem is that there's display:none on a container until the
user does something. Many tab widgets work this way, and there's
user does something. Many tab widgets work this way, and there's
...
...
NEWS.txt
View file @
89bbfef5
Flot x.x
Flot x.x
--------
--------
API changes:
Axis labels are now drawn with canvas text with some parsing to
support newlines. This solves various issues but also means that they
no longer support HTML markup, can be accessed as DOM elements or
styled directly with CSS. Some older browsers lack this function of
the canvas API (this doesn't affect IE); if this is a problem, either
continue using an older version of Flot or try an emulation helper
such as canvas-text or Flashcanvas.
Changes:
- Canvas text support for labels (sponsored by YCharts.com).
Bug fixes
Bug fixes
- Fix problem with null values and pie plugin (patch by gcruxifix,
- Fix problem with null values and pie plugin (patch by gcruxifix,
issue 500).
issue 500).
- Fix problem with threshold plugin and bars (based on patch by kaarlenkaski)
- Fix problem with threshold plugin and bars (based on patch by
kaarlenkaski, issue 348).
- Fix axis box calculations so the boxes include the outermost part of
the labels too.
Flot 0.7
Flot 0.7
--------
--------
...
...
examples/interacting-axes.html
View file @
89bbfef5
...
@@ -32,10 +32,10 @@ $(function () {
...
@@ -32,10 +32,10 @@ $(function () {
}
}
var
data
=
[
var
data
=
[
{
data
:
generate
(
0
,
10
,
function
(
x
)
{
return
Math
.
sqrt
(
x
)}),
xaxis
:
1
,
yaxis
:
1
},
{
data
:
generate
(
0
,
10
,
function
(
x
)
{
return
Math
.
sqrt
(
x
)
;
}),
xaxis
:
1
,
yaxis
:
1
},
{
data
:
generate
(
0
,
10
,
function
(
x
)
{
return
Math
.
sin
(
x
)}),
xaxis
:
1
,
yaxis
:
2
},
{
data
:
generate
(
0
,
10
,
function
(
x
)
{
return
Math
.
sin
(
x
)
;
}),
xaxis
:
1
,
yaxis
:
2
},
{
data
:
generate
(
0
,
10
,
function
(
x
)
{
return
Math
.
cos
(
x
)}),
xaxis
:
1
,
yaxis
:
3
},
{
data
:
generate
(
0
,
10
,
function
(
x
)
{
return
Math
.
cos
(
x
)
;
}),
xaxis
:
1
,
yaxis
:
3
},
{
data
:
generate
(
2
,
10
,
function
(
x
)
{
return
Math
.
tan
(
x
)}),
xaxis
:
2
,
yaxis
:
4
}
{
data
:
generate
(
2
,
10
,
function
(
x
)
{
return
Math
.
tan
(
x
)
;
}),
xaxis
:
2
,
yaxis
:
4
}
];
];
var
plot
=
$
.
plot
(
$
(
"#placeholder"
),
var
plot
=
$
.
plot
(
$
(
"#placeholder"
),
...
@@ -54,29 +54,11 @@ $(function () {
...
@@ -54,29 +54,11 @@ $(function () {
});
});
// now for each axis, create a div
// now for each axis, create a div
function
getBoundingBoxForAxis
(
plot
,
axis
)
{
var
left
=
axis
.
box
.
left
,
top
=
axis
.
box
.
top
,
right
=
left
+
axis
.
box
.
width
,
bottom
=
top
+
axis
.
box
.
height
;
// some ticks may stick out, enlarge the box to encompass all ticks
var
cls
=
axis
.
direction
+
axis
.
n
+
'Axis'
;
plot
.
getPlaceholder
().
find
(
'.'
+
cls
+
' .tickLabel'
).
each
(
function
()
{
var
pos
=
$
(
this
).
position
();
left
=
Math
.
min
(
pos
.
left
,
left
);
top
=
Math
.
min
(
pos
.
top
,
top
);
right
=
Math
.
max
(
Math
.
round
(
pos
.
left
)
+
$
(
this
).
outerWidth
(),
right
);
bottom
=
Math
.
max
(
Math
.
round
(
pos
.
top
)
+
$
(
this
).
outerHeight
(),
bottom
);
});
return
{
left
:
left
,
top
:
top
,
width
:
right
-
left
,
height
:
bottom
-
top
};
}
$
.
each
(
plot
.
getAxes
(),
function
(
i
,
axis
)
{
$
.
each
(
plot
.
getAxes
(),
function
(
i
,
axis
)
{
if
(
!
axis
.
show
)
if
(
!
axis
.
show
)
return
;
return
;
var
box
=
getBoundingBoxForAxis
(
plot
,
axis
)
;
var
box
=
axis
.
box
;
$
(
'<div class="axisTarget" style="position:absolute;left:'
+
box
.
left
+
'px;top:'
+
box
.
top
+
'px;width:'
+
box
.
width
+
'px;height:'
+
box
.
height
+
'px"></div>'
)
$
(
'<div class="axisTarget" style="position:absolute;left:'
+
box
.
left
+
'px;top:'
+
box
.
top
+
'px;width:'
+
box
.
width
+
'px;height:'
+
box
.
height
+
'px"></div>'
)
.
data
(
'axis.direction'
,
axis
.
direction
)
.
data
(
'axis.direction'
,
axis
.
direction
)
...
...
jquery.flot.js
View file @
89bbfef5
...
@@ -57,6 +57,7 @@
...
@@ -57,6 +57,7 @@
show
:
null
,
// null = auto-detect, true = always, false = never
show
:
null
,
// null = auto-detect, true = always, false = never
position
:
"bottom"
,
// or "top"
position
:
"bottom"
,
// or "top"
mode
:
null
,
// null or "time"
mode
:
null
,
// null or "time"
font
:
null
,
// null (derived from CSS in placeholder) or object like { size: 11, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }
color
:
null
,
// base color, labels, ticks
color
:
null
,
// base color, labels, ticks
tickColor
:
null
,
// possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"
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
transform
:
null
,
// null or f: number -> number to transform axis
...
@@ -844,80 +845,72 @@
...
@@ -844,80 +845,72 @@
}
}
function
measureTickLabels
(
axis
)
{
function
measureTickLabels
(
axis
)
{
var
opts
=
axis
.
options
,
i
,
ticks
=
axis
.
ticks
||
[],
labels
=
[],
var
opts
=
axis
.
options
,
ticks
=
axis
.
ticks
||
[],
l
,
w
=
opts
.
labelWidth
,
h
=
opts
.
labelHeight
,
dummyDiv
;
axisw
=
opts
.
labelWidth
||
0
,
axish
=
opts
.
labelHeight
||
0
,
f
=
axis
.
font
;
function
makeDummyDiv
(
labels
,
width
)
{
if
(
opts
.
labelWidth
==
null
||
opts
.
labelHeight
==
null
)
{
return
$
(
'<div style="position:absolute;top:-10000px;'
+
width
+
'font-size:smaller">'
+
ctx
.
save
();
'<div class="'
+
axis
.
direction
+
'Axis '
+
axis
.
direction
+
axis
.
n
+
'Axis">'
ctx
.
font
=
f
.
style
+
" "
+
f
.
variant
+
" "
+
f
.
weight
+
" "
+
f
.
size
+
"px '"
+
f
.
family
+
"'"
;
+
labels
.
join
(
""
)
+
'</div></div>'
)
.
appendTo
(
placeholder
);
}
if
(
axis
.
direction
==
"x"
)
{
for
(
var
i
=
0
;
i
<
ticks
.
length
;
++
i
)
{
// to avoid measuring the widths of the labels (it's slow), we
var
t
=
ticks
[
i
];
// construct fixed-size boxes and put the labels inside
// them, we don't need the exact figures and the
t
.
lines
=
[];
// fixed-size box content is easy to center
t
.
width
=
t
.
height
=
0
;
if
(
w
==
null
)
w
=
Math
.
floor
(
canvasWidth
/
(
ticks
.
length
>
0
?
ticks
.
length
:
1
));
if
(
!
t
.
label
)
continue
;
// measure x label heights
if
(
h
==
null
)
{
// accept various kinds of newlines, including HTML ones
labels
=
[];
// (you can actually split directly on regexps in Javascript,
for
(
i
=
0
;
i
<
ticks
.
length
;
++
i
)
{
// but IE is unfortunately broken)
l
=
ticks
[
i
].
label
;
var
lines
=
t
.
label
.
replace
(
/<br
?\/?
>|
\r\n
|
\r
/g
,
"
\n
"
).
split
(
"
\n
"
);
if
(
l
)
for
(
var
j
=
0
;
j
<
lines
.
length
;
++
j
)
{
labels
.
push
(
'<div class="tickLabel" style="float:left;width:'
+
w
+
'px">'
+
l
+
'</div>'
);
var
line
=
{
text
:
lines
[
j
]
},
}
m
=
ctx
.
measureText
(
line
.
text
);
line
.
width
=
m
.
width
;
// m.height might not be defined, not in the
// standard yet
line
.
height
=
m
.
height
!=
null
?
m
.
height
:
f
.
size
;
// add a bit of margin since font rendering is
// not pixel perfect and cut off letters look
// bad, this also doubles as spacing between
// lines
line
.
height
+=
Math
.
round
(
f
.
size
*
0.15
);
t
.
width
=
Math
.
max
(
line
.
width
,
t
.
width
);
t
.
height
+=
line
.
height
;
if
(
labels
.
length
>
0
)
{
t
.
lines
.
push
(
line
);
// stick them all in the same div and measure
// collective height
labels
.
push
(
'<div style="clear:left"></div>'
);
dummyDiv
=
makeDummyDiv
(
labels
,
"width:10000px;"
);
h
=
dummyDiv
.
height
();
dummyDiv
.
remove
();
}
}
if
(
opts
.
labelWidth
==
null
)
axisw
=
Math
.
max
(
axisw
,
t
.
width
);
if
(
opts
.
labelHeight
==
null
)
axish
=
Math
.
max
(
axish
,
t
.
height
);
}
}
}
ctx
.
restore
();
else
if
(
w
==
null
||
h
==
null
)
{
// calculate y label dimensions
for
(
i
=
0
;
i
<
ticks
.
length
;
++
i
)
{
l
=
ticks
[
i
].
label
;
if
(
l
)
labels
.
push
(
'<div class="tickLabel">'
+
l
+
'</div>'
);
}
if
(
labels
.
length
>
0
)
{
dummyDiv
=
makeDummyDiv
(
labels
,
""
);
if
(
w
==
null
)
w
=
dummyDiv
.
children
().
width
();
if
(
h
==
null
)
h
=
dummyDiv
.
find
(
"div.tickLabel"
).
height
();
dummyDiv
.
remove
();
}
}
}
if
(
w
==
null
)
axis
.
labelWidth
=
axisw
;
w
=
0
;
axis
.
labelHeight
=
axish
;
if
(
h
==
null
)
h
=
0
;
axis
.
labelWidth
=
w
;
axis
.
labelHeight
=
h
;
}
}
function
allocateAxisBoxFirstPhase
(
axis
)
{
function
allocateAxisBoxFirstPhase
(
axis
)
{
// find the bounding box of the axis by looking at label
// find the bounding box of the axis by looking at label
// widths/heights and ticks, make room by diminishing the
// widths/heights and ticks, make room by diminishing the
// plotOffset
// 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
,
var
lw
=
axis
.
labelWidth
,
lh
=
axis
.
labelHeight
,
lh
=
axis
.
labelHeight
,
pos
=
axis
.
options
.
position
,
pos
=
axis
.
options
.
position
,
tickLength
=
axis
.
options
.
tickLength
,
tickLength
=
axis
.
options
.
tickLength
,
axis
m
argin
=
options
.
grid
.
axisMargin
,
axis
M
argin
=
options
.
grid
.
axisMargin
,
padding
=
options
.
grid
.
labelMargin
,
padding
=
options
.
grid
.
labelMargin
,
all
=
axis
.
direction
==
"x"
?
xaxes
:
yaxes
,
all
=
axis
.
direction
==
"x"
?
xaxes
:
yaxes
,
index
;
index
;
...
@@ -927,20 +920,21 @@
...
@@ -927,20 +920,21 @@
return
a
&&
a
.
options
.
position
==
pos
&&
a
.
reserveSpace
;
return
a
&&
a
.
options
.
position
==
pos
&&
a
.
reserveSpace
;
});
});
if
(
$
.
inArray
(
axis
,
samePosition
)
==
samePosition
.
length
-
1
)
if
(
$
.
inArray
(
axis
,
samePosition
)
==
samePosition
.
length
-
1
)
axis
m
argin
=
0
;
// outermost
axis
M
argin
=
0
;
// outermost
// determine tick length - if we're innermost, we can use "full"
// determine tick length - if we're innermost, we can use "full"
if
(
tickLength
==
null
)
if
(
tickLength
==
null
)
{
tickLength
=
"full"
;
var
sameDirection
=
$
.
grep
(
all
,
function
(
a
)
{
return
a
&&
a
.
reserveSpace
;
var
sameDirection
=
$
.
grep
(
all
,
function
(
a
)
{
});
return
a
&&
a
.
reserveSpace
;
});
var
innermost
=
$
.
inArray
(
axis
,
sameDirection
)
==
0
;
if
(
!
innermost
&&
tickLength
==
"full"
)
tickLength
=
5
;
var
innermost
=
$
.
inArray
(
axis
,
sameDirection
)
==
0
;
if
(
innermost
)
tickLength
=
"full"
else
tickLength
=
5
;
}
if
(
!
isNaN
(
+
tickLength
))
if
(
!
isNaN
(
+
tickLength
))
padding
+=
+
tickLength
;
padding
+=
+
tickLength
;
...
@@ -949,23 +943,23 @@
...
@@ -949,23 +943,23 @@
lh
+=
padding
;
lh
+=
padding
;
if
(
pos
==
"bottom"
)
{
if
(
pos
==
"bottom"
)
{
plotOffset
.
bottom
+=
lh
+
axis
m
argin
;
plotOffset
.
bottom
+=
lh
+
axis
M
argin
;
axis
.
box
=
{
top
:
canvasHeight
-
plotOffset
.
bottom
,
height
:
lh
};
axis
.
box
=
{
top
:
canvasHeight
-
plotOffset
.
bottom
,
height
:
lh
};
}
}
else
{
else
{
axis
.
box
=
{
top
:
plotOffset
.
top
+
axis
m
argin
,
height
:
lh
};
axis
.
box
=
{
top
:
plotOffset
.
top
+
axis
M
argin
,
height
:
lh
};
plotOffset
.
top
+=
lh
+
axis
m
argin
;
plotOffset
.
top
+=
lh
+
axis
M
argin
;
}
}
}
}
else
{
else
{
lw
+=
padding
;
lw
+=
padding
;
if
(
pos
==
"left"
)
{
if
(
pos
==
"left"
)
{
axis
.
box
=
{
left
:
plotOffset
.
left
+
axis
m
argin
,
width
:
lw
};
axis
.
box
=
{
left
:
plotOffset
.
left
+
axis
M
argin
,
width
:
lw
};
plotOffset
.
left
+=
lw
+
axis
m
argin
;
plotOffset
.
left
+=
lw
+
axis
M
argin
;
}
}
else
{
else
{
plotOffset
.
right
+=
lw
+
axis
m
argin
;
plotOffset
.
right
+=
lw
+
axis
M
argin
;
axis
.
box
=
{
left
:
canvasWidth
-
plotOffset
.
right
,
width
:
lw
};
axis
.
box
=
{
left
:
canvasWidth
-
plotOffset
.
right
,
width
:
lw
};
}
}
}
}
...
@@ -978,22 +972,59 @@
...
@@ -978,22 +972,59 @@
}
}
function
allocateAxisBoxSecondPhase
(
axis
)
{
function
allocateAxisBoxSecondPhase
(
axis
)
{
// set remaining bounding box coordinates
// now that all axis boxes have been placed in one
// dimension, we can set the remaining dimension coordinates
if
(
axis
.
direction
==
"x"
)
{
if
(
axis
.
direction
==
"x"
)
{
axis
.
box
.
left
=
plotOffset
.
left
;
axis
.
box
.
left
=
plotOffset
.
left
-
axis
.
labelWidth
/
2
;
axis
.
box
.
width
=
plot
Width
;
axis
.
box
.
width
=
canvasWidth
-
plotOffset
.
left
-
plotOffset
.
right
+
axis
.
label
Width
;
}
}
else
{
else
{
axis
.
box
.
top
=
plotOffset
.
top
;
axis
.
box
.
top
=
plotOffset
.
top
-
axis
.
labelHeight
/
2
;
axis
.
box
.
height
=
plot
Height
;
axis
.
box
.
height
=
canvasHeight
-
plotOffset
.
bottom
-
plotOffset
.
top
+
axis
.
label
Height
;
}
}
}
}
function
adjustLayoutForThingsStickingOut
()
{
// possibly adjust plot offset to ensure everything stays
// inside the canvas and isn't clipped off
var
minMargin
=
options
.
grid
.
minBorderMargin
,
margins
=
{
x
:
0
,
y
:
0
},
i
,
axis
;
// check stuff from the plot (FIXME: this should just read
// a value from the series, otherwise it's impossible to
// customize)
if
(
minMargin
==
null
)
{
minMargin
=
0
;
for
(
i
=
0
;
i
<
series
.
length
;
++
i
)
minMargin
=
Math
.
max
(
minMargin
,
2
*
(
series
[
i
].
points
.
radius
+
series
[
i
].
points
.
lineWidth
/
2
));
}
margins
.
x
=
margins
.
y
=
minMargin
;
// check axis labels, note we don't check the actual
// labels but instead use the overall width/height to not
// jump as much around with replots
$
.
each
(
allAxes
(),
function
(
_
,
axis
)
{
var
dir
=
axis
.
direction
;
if
(
axis
.
reserveSpace
)
margins
[
dir
]
=
Math
.
max
(
margins
[
dir
],
(
dir
==
"x"
?
axis
.
labelWidth
:
axis
.
labelHeight
)
/
2
);
});
plotOffset
.
left
=
Math
.
max
(
margins
.
x
,
plotOffset
.
left
);
plotOffset
.
right
=
Math
.
max
(
margins
.
x
,
plotOffset
.
right
);
plotOffset
.
top
=
Math
.
max
(
margins
.
y
,
plotOffset
.
top
);
plotOffset
.
bottom
=
Math
.
max
(
margins
.
y
,
plotOffset
.
bottom
);
}
function
setupGrid
()
{
function
setupGrid
()
{
var
i
,
axes
=
allAxes
();
var
i
,
axes
=
allAxes
(),
showGrid
=
options
.
grid
.
show
;
// first calculate the plot and axis box dimensions
// init plot offset
for
(
var
a
in
plotOffset
)
plotOffset
[
a
]
=
showGrid
?
options
.
grid
.
borderWidth
:
0
;
// init axes
$
.
each
(
axes
,
function
(
_
,
axis
)
{
$
.
each
(
axes
,
function
(
_
,
axis
)
{
axis
.
show
=
axis
.
options
.
show
;
axis
.
show
=
axis
.
options
.
show
;
if
(
axis
.
show
==
null
)
if
(
axis
.
show
==
null
)
...
@@ -1003,11 +1034,19 @@
...
@@ -1003,11 +1034,19 @@
setRange
(
axis
);
setRange
(
axis
);
});
});
if
(
showGrid
)
{
// determine from the placeholder the font size ~ height of font ~ 1 em
var
fontDefaults
=
{
style
:
placeholder
.
css
(
"font-style"
),
size
:
Math
.
round
(
0.8
*
(
+
placeholder
.
css
(
"font-size"
).
replace
(
"px"
,
""
)
||
13
)),
variant
:
placeholder
.
css
(
"font-variant"
),
weight
:
placeholder
.
css
(
"font-weight"
),
family
:
placeholder
.
css
(
"font-family"
)
};
allocatedAxes
=
$
.
grep
(
axes
,
function
(
axis
)
{
return
axis
.
reserveSpace
;
});
var
allocatedAxes
=
$
.
grep
(
axes
,
function
(
axis
)
{
return
axis
.
reserveSpace
;
});
plotOffset
.
left
=
plotOffset
.
right
=
plotOffset
.
top
=
plotOffset
.
bottom
=
0
;
if
(
options
.
grid
.
show
)
{
$
.
each
(
allocatedAxes
,
function
(
_
,
axis
)
{
$
.
each
(
allocatedAxes
,
function
(
_
,
axis
)
{
// make the ticks
// make the ticks
setupTickGeneration
(
axis
);
setupTickGeneration
(
axis
);
...
@@ -1015,44 +1054,32 @@
...
@@ -1015,44 +1054,32 @@
snapRangeToTicks
(
axis
,
axis
.
ticks
);
snapRangeToTicks
(
axis
,
axis
.
ticks
);
// find labelWidth/Height for axis
// find labelWidth/Height for axis
axis
.
font
=
$
.
extend
({},
fontDefaults
,
axis
.
options
.
font
);
measureTickLabels
(
axis
);
measureTickLabels
(
axis
);
});
});
// with all dimensions in house, we can compute the
// with all dimensions calculated, we can compute the
// axis boxes, start from the outside (reverse order)
// axis bounding boxes, start from the outside
// (reverse order)
for
(
i
=
allocatedAxes
.
length
-
1
;
i
>=
0
;
--
i
)
for
(
i
=
allocatedAxes
.
length
-
1
;
i
>=
0
;
--
i
)
allocateAxisBoxFirstPhase
(
allocatedAxes
[
i
]);
allocateAxisBoxFirstPhase
(
allocatedAxes
[
i
]);
// make sure we've got enough space for things that
// make sure we've got enough space for things that
// might stick out
// might stick out
var
minMargin
=
options
.
grid
.
minBorderMargin
;
adjustLayoutForThingsStickingOut
();
if
(
minMargin
==
null
)
{
minMargin
=
0
;
$
.
each
(
allocatedAxes
,
function
(
_
,
axis
)
{
for
(
i
=
0
;
i
<
series
.
length
;
++
i
)
allocateAxisBoxSecondPhase
(
axis
);
minMargin
=
Math
.
max
(
minMargin
,
series
[
i
].
points
.
radius
+
series
[
i
].
points
.
lineWidth
/
2
);
});
}
for
(
var
a
in
plotOffset
)
{
plotOffset
[
a
]
+=
options
.
grid
.
borderWidth
;
plotOffset
[
a
]
=
Math
.
max
(
minMargin
,
plotOffset
[
a
]);
}
}
}
plotWidth
=
canvasWidth
-
plotOffset
.
left
-
plotOffset
.
right
;
plotWidth
=
canvasWidth
-
plotOffset
.
left
-
plotOffset
.
right
;
plotHeight
=
canvasHeight
-
plotOffset
.
bottom
-
plotOffset
.
top
;
plotHeight
=
canvasHeight
-
plotOffset
.
bottom
-
plotOffset
.
top
;
// now we got the proper plot
Width/Height
, we can compute the scaling
// now we got the proper plot
dimensions
, we can compute the scaling
$
.
each
(
axes
,
function
(
_
,
axis
)
{
$
.
each
(
axes
,
function
(
_
,
axis
)
{
setTransformationHelpers
(
axis
);
setTransformationHelpers
(
axis
);
});
});
if
(
options
.
grid
.
show
)
{
$
.
each
(
allocatedAxes
,
function
(
_
,
axis
)
{
allocateAxisBoxSecondPhase
(
axis
);
});
insertAxisLabels
();
}
insertLegend
();
insertLegend
();
}
}
...
@@ -1419,8 +1446,10 @@
...
@@ -1419,8 +1446,10 @@
if
(
grid
.
show
&&
grid
.
backgroundColor
)
if
(
grid
.
show
&&
grid
.
backgroundColor
)
drawBackground
();
drawBackground
();
if
(
grid
.
show
&&
!
grid
.
aboveData
)
if
(
grid
.
show
&&
!
grid
.
aboveData
)
{
drawGrid
();
drawGrid
();
drawAxisLabels
();
}
for
(
var
i
=
0
;
i
<
series
.
length
;
++
i
)
{
for
(
var
i
=
0
;
i
<
series
.
length
;
++
i
)
{
executeHooks
(
hooks
.
drawSeries
,
[
ctx
,
series
[
i
]]);
executeHooks
(
hooks
.
drawSeries
,
[
ctx
,
series
[
i
]]);
...
@@ -1429,8 +1458,10 @@
...
@@ -1429,8 +1458,10 @@
executeHooks
(
hooks
.
draw
,
[
ctx
]);
executeHooks
(
hooks
.
draw
,
[
ctx
]);
if
(
grid
.
show
&&
grid
.
aboveData
)
if
(
grid
.
show
&&
grid
.
aboveData
)
{
drawGrid
();
drawGrid
();
drawAxisLabels
();
}
}
}
function
extractRange
(
ranges
,
coord
)
{
function
extractRange
(
ranges
,
coord
)
{
...
@@ -1650,59 +1681,68 @@
...
@@ -1650,59 +1681,68 @@
ctx
.
restore
();
ctx
.
restore
();
}
}
function
insertAxisLabels
()
{
function
drawAxisLabels
()
{
placeholder
.
find
(
".tickLabels"
).
remove
();
ctx
.
save
();
var
html
=
[
'<div class="tickLabels" style="font-size:smaller">'
];
var
axes
=
allAxes
();
$
.
each
(
allAxes
(),
function
(
_
,
axis
)
{
for
(
var
j
=
0
;
j
<
axes
.
length
;
++
j
)
{
var
box
=
axis
.
box
,
f
=
axis
.
font
;
var
axis
=
axes
[
j
],
box
=
axis
.
box
;
// placeholder.append('<div style="position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width + 'px;height:' + box.height + 'px"></div>') // debug
if
(
!
axis
.
show
)
continue
;
ctx
.
fillStyle
=
axis
.
options
.
color
;
//debug: html.push('<div style="position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width + 'px;height:' + box.height + 'px"></div>')
ctx
.
font
=
f
.
style
+
" "
+
f
.
variant
+
" "
+
f
.
weight
+
" "
+
f
.
size
+
"px '"
+
f
.
family
+
"'"
;
html
.
push
(
'<div class="'
+
axis
.
direction
+
'Axis '
+
axis
.
direction
+
axis
.
n
+
'Axis" style="color:'
+
axis
.
options
.
color
+
'">'
);
ctx
.
textAlign
=
"start"
;
// middle align the labels - top would be more
// natural, but browsers can differ a pixel or two in
// where they consider the top to be, so instead we
// middle align to minimize variation between browsers
// and compensate when calculating the coordinates
ctx
.
textBaseline
=
"middle"
;
for
(
var
i
=
0
;
i
<
axis
.
ticks
.
length
;
++
i
)
{
for
(
var
i
=
0
;
i
<
axis
.
ticks
.
length
;
++
i
)
{
var
tick
=
axis
.
ticks
[
i
];
var
tick
=
axis
.
ticks
[
i
];
if
(
!
tick
.
label
||
tick
.
v
<
axis
.
min
||
tick
.
v
>
axis
.
max
)
if
(
!
tick
.
label
||
tick
.
v
<
axis
.
min
||
tick
.
v
>
axis
.
max
)
continue
;
continue
;
var
pos
=
{},
align
;
var
x
,
y
,
offset
=
0
,
line
;
for
(
var
k
=
0
;
k
<
tick
.
lines
.
length
;
++
k
)
{
if
(
axis
.
direction
==
"x"
)
{
line
=
tick
.
lines
[
k
];
align
=
"center"
;
pos
.
left
=
Math
.
round
(
plotOffset
.
left
+
axis
.
p2c
(
tick
.
v
)
-
axis
.
labelWidth
/
2
);
if
(
axis
.
direction
==
"x"
)
{
if
(
axis
.
position
==
"bottom"
)
x
=
plotOffset
.
left
+
axis
.
p2c
(
tick
.
v
)
-
line
.
width
/
2
;
pos
.
top
=
box
.
top
+
box
.
padding
;
if
(
axis
.
position
==
"bottom"
)
else
y
=
box
.
top
+
box
.
padding
;
pos
.
bottom
=
canvasHeight
-
(
box
.
top
+
box
.
height
-
box
.
padding
);
else
}
y
=
box
.
top
+
box
.
height
-
box
.
padding
-
tick
.
height
;
else
{
pos
.
top
=
Math
.
round
(
plotOffset
.
top
+
axis
.
p2c
(
tick
.
v
)
-
axis
.
labelHeight
/
2
);
if
(
axis
.
position
==
"left"
)
{
pos
.
right
=
canvasWidth
-
(
box
.
left
+
box
.
width
-
box
.
padding
)
align
=
"right"
;
}
}
else
{
else
{
pos
.
left
=
box
.
left
+
box
.
padding
;
y
=
plotOffset
.
top
+
axis
.
p2c
(
tick
.
v
)
-
tick
.
height
/
2
;
align
=
"left"
;
if
(
axis
.
position
==
"left"
)
x
=
box
.
left
+
box
.
width
-
box
.
padding
-
line
.
width
;
else
x
=
box
.
left
+
box
.
padding
;
}
}
}
pos
.
width
=
axis
.
labelWidth
;
var
style
=
[
"position:absolute"
,
"text-align:"
+
align
];
// account for middle aligning and line number
for
(
var
a
in
pos
)
y
+=
line
.
height
/
2
+
offset
;
style
.
push
(
a
+
":"
+
pos
[
a
]
+
"px"
)
offset
+=
line
.
height
;
html
.
push
(
'<div class="tickLabel" style="'
+
style
.
join
(
';'
)
+
'">'
+
tick
.
label
+
'</div>'
);
if
(
$
.
browser
.
opera
)
{
// FIXME: UGLY BROWSER DETECTION
// round the coordinates since Opera
// otherwise switches to more ugly
// rendering (probably non-hinted) and
// offset the y coordinates since it seems
// to be off pretty consistently compared
// to the other browsers
x
=
Math
.
floor
(
x
);
y
=
Math
.
ceil
(
y
-
2
);
}
ctx
.
fillText
(
line
.
text
,
x
,
y
);
}
}
}
html
.
push
(
'</div>'
);
});
}
html
.
push
(
'</div>'
);
placeholder
.
append
(
html
.
join
(
""
)
);
ctx
.
restore
(
);
}
}
function
drawSeries
(
series
)
{
function
drawSeries
(
series
)
{
...
...
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