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
0a601d03
Commit
0a601d03
authored
Nov 25, 2012
by
David Schnur
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleaned up whitespace, braces and strings.
parent
2f7cfcb5
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
414 additions
and
373 deletions
+414
-373
jquery.flot.pie.js
jquery.flot.pie.js
+414
-373
No files found.
jquery.flot.pie.js
View file @
0a601d03
/*
Flot plugin for rendering pie charts. The plugin assumes the data is
coming is as a single data value for each series, and each of those
values is a positive value or zero (negative numbers don't make
any sense and will cause strange effects). The data values do
NOT need to be passed in as percentage values because it
internally calculates the total and percentages.
Flot plugin for rendering pie charts.
Copyright (c) 2007-2012 IOLA and Ole Laursen.
Licensed under the MIT license.
The plugin assumes that each series has a single data value, and that
each value is a positive integer or zero. Negative numbers don't make
sense for a pie chart, and have unpredictable results. The values do
NOT need to be passed in as percentages; the plugin will calculate the
total and per-slice percentages internally.
* Created by Brian Medendorp, June 2009
* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars
...
...
@@ -16,7 +20,6 @@ internally calculates the total and percentages.
2009-11-17: Added IE hover capability submitted by Anthony Aragues
2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well)
Available options are:
series: {
pie: {
...
...
@@ -58,10 +61,10 @@ More detail and specific examples can be found in the included HTML file.
*/
(
function
(
$
)
{
function
init
(
plot
)
// this is the "body" of the plugin
{
(
function
(
$
)
{
function
init
(
plot
)
{
var
canvas
=
null
;
var
canvasWidth
=
0
;
var
canvasHeight
=
0
;
...
...
@@ -78,271 +81,287 @@ More detail and specific examples can be found in the included HTML file.
var
raw
=
false
;
// interactive variables
var
highlights
=
[];
// add hook to determine if pie plugin in enabled, and then perform necessary operations
plot
.
hooks
.
processOptions
.
push
(
checkPieEnabled
);
plot
.
hooks
.
bindEvents
.
push
(
bindEvents
);
// check to see if the pie plugin is enabled
function
checkPieEnabled
(
plot
,
options
)
{
if
(
options
.
series
.
pie
.
show
)
{
function
checkPieEnabled
(
plot
,
options
)
{
if
(
options
.
series
.
pie
.
show
)
{
//disable grid
options
.
grid
.
show
=
false
;
// set labels.show
if
(
options
.
series
.
pie
.
label
.
show
==
'auto'
)
if
(
options
.
legend
.
show
)
if
(
options
.
series
.
pie
.
label
.
show
==
"auto"
)
{
if
(
options
.
legend
.
show
)
{
options
.
series
.
pie
.
label
.
show
=
false
;
else
}
else
{
options
.
series
.
pie
.
label
.
show
=
true
;
}
}
// set radius
if
(
options
.
series
.
pie
.
radius
==
'auto'
)
if
(
options
.
series
.
pie
.
label
.
show
)
if
(
options
.
series
.
pie
.
radius
==
"auto"
)
{
if
(
options
.
series
.
pie
.
label
.
show
)
{
options
.
series
.
pie
.
radius
=
3
/
4
;
else
}
else
{
options
.
series
.
pie
.
radius
=
1
;
}
}
// ensure sane tilt
if
(
options
.
series
.
pie
.
tilt
>
1
)
options
.
series
.
pie
.
tilt
=
1
;
if
(
options
.
series
.
pie
.
tilt
<
0
)
options
.
series
.
pie
.
tilt
=
0
;
if
(
options
.
series
.
pie
.
tilt
>
1
)
{
options
.
series
.
pie
.
tilt
=
1
;
}
else
if
(
options
.
series
.
pie
.
tilt
<
0
)
{
options
.
series
.
pie
.
tilt
=
0
;
}
// add processData hook to do transformations on the data
plot
.
hooks
.
processDatapoints
.
push
(
processDatapoints
);
plot
.
hooks
.
drawOverlay
.
push
(
drawOverlay
);
// add draw hook
// draw hook
plot
.
hooks
.
draw
.
push
(
draw
);
}
}
// bind hoverable events
function
bindEvents
(
plot
,
eventHolder
)
{
function
bindEvents
(
plot
,
eventHolder
)
{
var
options
=
plot
.
getOptions
();
if
(
options
.
series
.
pie
.
show
)
{
if
(
options
.
grid
.
hoverable
)
{
eventHolder
.
unbind
(
"mousemove"
).
mousemove
(
onMouseMove
);
}
if
(
options
.
grid
.
clickable
)
{
eventHolder
.
unbind
(
"click"
).
click
(
onClick
);
}
}
}
if
(
options
.
series
.
pie
.
show
&&
options
.
grid
.
hoverable
)
eventHolder
.
unbind
(
'mousemove'
).
mousemove
(
onMouseMove
);
// debugging function that prints out an object
if
(
options
.
series
.
pie
.
show
&&
options
.
grid
.
clickable
)
eventHolder
.
unbind
(
'click'
).
click
(
onClick
);
}
function
alertObject
(
obj
)
{
var
msg
=
""
;
// debugging function that prints out an object
function
alertObject
(
obj
)
{
var
msg
=
''
;
function
traverse
(
obj
,
depth
)
{
if
(
!
depth
)
function
traverse
(
obj
,
depth
)
{
if
(
!
depth
)
{
depth
=
0
;
}
for
(
var
i
=
0
;
i
<
obj
.
length
;
++
i
)
{
for
(
var
j
=
0
;
j
<
depth
;
j
++
)
msg
+=
'
\
t'
;
if
(
typeof
obj
[
i
]
==
"object"
)
{
// its an object
msg
+=
''
+
i
+
':
\
n'
;
traverse
(
obj
[
i
],
depth
+
1
);
for
(
var
j
=
0
;
j
<
depth
;
j
++
)
{
msg
+=
"
\
t"
;
}
else
{
// its a value
msg
+=
''
+
i
+
': '
+
obj
[
i
]
+
'
\
n'
;
if
(
typeof
obj
[
i
]
==
"object"
)
{
msg
+=
""
+
i
+
":
\n
"
;
traverse
(
obj
[
i
],
depth
+
1
);
}
else
{
msg
+=
""
+
i
+
": "
+
obj
[
i
]
+
"
\n
"
;
}
}
}
traverse
(
obj
);
alert
(
msg
);
}
function
calcTotal
(
data
)
{
for
(
var
i
=
0
;
i
<
data
.
length
;
++
i
)
{
function
calcTotal
(
data
)
{
for
(
var
i
=
0
;
i
<
data
.
length
;
++
i
)
{
var
item
=
parseFloat
(
data
[
i
].
data
[
0
][
1
]);
if
(
item
)
if
(
item
)
{
total
+=
item
;
}
}
}
function
processDatapoints
(
plot
,
series
,
data
,
datapoints
)
{
if
(
!
processed
)
{
function
processDatapoints
(
plot
,
series
,
data
,
datapoints
)
{
if
(
!
processed
)
{
processed
=
true
;
canvas
=
plot
.
getCanvas
();
target
=
$
(
canvas
).
parent
();
options
=
plot
.
getOptions
();
canvasWidth
=
plot
.
getPlaceholder
().
width
();
canvasHeight
=
plot
.
getPlaceholder
().
height
();
plot
.
setData
(
combine
(
plot
.
getData
()));
}
}
function
setupPie
()
{
legendWidth
=
target
.
children
().
filter
(
'.legend'
).
children
().
width
()
||
0
;
function
setupPie
()
{
legendWidth
=
target
.
children
().
filter
(
".legend"
).
children
().
width
()
||
0
;
// calculate maximum radius and center point
maxRadius
=
Math
.
min
(
canvasWidth
,(
canvasHeight
/
options
.
series
.
pie
.
tilt
))
/
2
;
centerTop
=
(
canvasHeight
/
2
)
+
options
.
series
.
pie
.
offset
.
top
;
centerLeft
=
(
canvasWidth
/
2
);
if
(
options
.
series
.
pie
.
offset
.
left
==
'auto'
)
if
(
options
.
legend
.
position
.
match
(
'w'
))
centerLeft
+=
legendWidth
/
2
;
else
centerLeft
-=
legendWidth
/
2
;
else
maxRadius
=
Math
.
min
(
canvasWidth
,
canvasHeight
/
options
.
series
.
pie
.
tilt
)
/
2
;
centerTop
=
canvasHeight
/
2
+
options
.
series
.
pie
.
offset
.
top
;
centerLeft
=
canvasWidth
/
2
;
if
(
options
.
series
.
pie
.
offset
.
left
==
"auto"
)
{
if
(
options
.
legend
.
position
.
match
(
"w"
))
{
centerLeft
+=
legendWidth
/
2
;
}
else
{
centerLeft
-=
legendWidth
/
2
;
}
}
else
{
centerLeft
+=
options
.
series
.
pie
.
offset
.
left
;
}
if
(
centerLeft
<
maxRadius
)
if
(
centerLeft
<
maxRadius
)
{
centerLeft
=
maxRadius
;
else
if
(
centerLeft
>
canvasWidth
-
maxRadius
)
centerLeft
=
canvasWidth
-
maxRadius
;
}
else
if
(
centerLeft
>
canvasWidth
-
maxRadius
)
{
centerLeft
=
canvasWidth
-
maxRadius
;
}
}
function
fixData
(
data
)
{
for
(
var
i
=
0
;
i
<
data
.
length
;
++
i
)
{
if
(
typeof
(
data
[
i
].
data
)
==
'number'
)
data
[
i
].
data
=
[[
1
,
data
[
i
].
data
]];
else
if
(
typeof
(
data
[
i
].
data
)
==
'undefined'
||
typeof
(
data
[
i
].
data
[
0
])
==
'undefined'
)
{
if
(
typeof
(
data
[
i
].
data
)
!=
'undefined'
&&
typeof
(
data
[
i
].
data
.
label
)
!=
'undefined'
)
function
fixData
(
data
)
{
for
(
var
i
=
0
;
i
<
data
.
length
;
++
i
)
{
if
(
typeof
(
data
[
i
].
data
)
==
"number"
)
{
data
[
i
].
data
=
[[
1
,
data
[
i
].
data
]];
}
else
if
(
typeof
(
data
[
i
].
data
)
==
"undefined"
||
typeof
(
data
[
i
].
data
[
0
])
==
"undefined"
)
{
if
(
typeof
(
data
[
i
].
data
)
!=
"undefined"
&&
typeof
(
data
[
i
].
data
.
label
)
!=
"undefined"
)
{
data
[
i
].
label
=
data
[
i
].
data
.
label
;
// fix weirdness coming from flot
data
[
i
].
data
=
[[
1
,
0
]];
}
data
[
i
].
data
=
[[
1
,
0
]];
}
}
return
data
;
}
function
combine
(
data
)
{
function
combine
(
data
)
{
data
=
fixData
(
data
);
calcTotal
(
data
);
var
combined
=
0
;
var
numCombined
=
0
;
var
color
=
options
.
series
.
pie
.
combine
.
color
;
var
newdata
=
[];
for
(
var
i
=
0
;
i
<
data
.
length
;
++
i
)
{
for
(
var
i
=
0
;
i
<
data
.
length
;
++
i
)
{
// make sure its a number
data
[
i
].
data
[
0
][
1
]
=
parseFloat
(
data
[
i
].
data
[
0
][
1
]);
if
(
!
data
[
i
].
data
[
0
][
1
])
if
(
!
data
[
i
].
data
[
0
][
1
])
{
data
[
i
].
data
[
0
][
1
]
=
0
;
}
if
(
data
[
i
].
data
[
0
][
1
]
/
total
<=
options
.
series
.
pie
.
combine
.
threshold
)
{
if
(
data
[
i
].
data
[
0
][
1
]
/
total
<=
options
.
series
.
pie
.
combine
.
threshold
)
{
combined
+=
data
[
i
].
data
[
0
][
1
];
numCombined
++
;
if
(
!
color
)
if
(
!
color
)
{
color
=
data
[
i
].
color
;
}
else
{
}
else
{
newdata
.
push
({
data
:
[[
1
,
data
[
i
].
data
[
0
][
1
]]],
data
:
[[
1
,
data
[
i
].
data
[
0
][
1
]]],
color
:
data
[
i
].
color
,
label
:
data
[
i
].
label
,
angle
:
(
data
[
i
].
data
[
0
][
1
]
*
(
Math
.
PI
*
2
))
/
total
,
percent
:
(
data
[
i
].
data
[
0
][
1
]
/
total
*
100
)
angle
:
data
[
i
].
data
[
0
][
1
]
*
Math
.
PI
*
2
/
total
,
percent
:
data
[
i
].
data
[
0
][
1
]
/
total
*
100
});
}
}
if
(
numCombined
>
0
)
if
(
numCombined
>
0
)
{
newdata
.
push
({
data
:
[[
1
,
combined
]],
data
:
[[
1
,
combined
]],
color
:
color
,
label
:
options
.
series
.
pie
.
combine
.
label
,
angle
:
(
combined
*
(
Math
.
PI
*
2
))
/
total
,
percent
:
(
combined
/
total
*
100
)
angle
:
combined
*
Math
.
PI
*
2
/
total
,
percent
:
combined
/
total
*
100
});
return
newdata
;
}
function
draw
(
plot
,
newCtx
)
{
if
(
!
target
)
return
;
// if no series were passed
ctx
=
newCtx
;
function
draw
(
plot
,
newCtx
)
{
if
(
!
target
)
{
return
;
// if no series were passed
}
ctx
=
newCtx
;
setupPie
();
var
slices
=
plot
.
getData
();
var
slices
=
plot
.
getData
();
var
attempts
=
0
;
while
(
redraw
&&
attempts
<
redrawAttempts
)
{
while
(
redraw
&&
attempts
<
redrawAttempts
)
{
redraw
=
false
;
if
(
attempts
>
0
)
if
(
attempts
>
0
)
{
maxRadius
*=
shrink
;
}
attempts
+=
1
;
clear
();
if
(
options
.
series
.
pie
.
tilt
<=
0.8
)
if
(
options
.
series
.
pie
.
tilt
<=
0.8
)
{
drawShadow
();
}
drawPie
();
}
if
(
attempts
>=
redrawAttempts
)
{
clear
();
target
.
prepend
(
'<div class="error">Could not draw pie with labels contained inside canvas</div>'
);
target
.
prepend
(
"<div class='error'>Could not draw pie with labels contained inside canvas</div>"
);
}
if
(
plot
.
setSeries
&&
plot
.
insertLegend
)
{
if
(
plot
.
setSeries
&&
plot
.
insertLegend
)
{
plot
.
setSeries
(
slices
);
plot
.
insertLegend
();
}
// we're actually done at this point, just defining internal functions at this point
function
clear
()
{
ctx
.
clearRect
(
0
,
0
,
canvasWidth
,
canvasHeight
);
target
.
children
().
filter
(
'.pieLabel, .pieLabelBackground'
).
remove
();
function
clear
()
{
ctx
.
clearRect
(
0
,
0
,
canvasWidth
,
canvasHeight
);
target
.
children
().
filter
(
".pieLabel, .pieLabelBackground"
).
remove
();
}
function
drawShadow
()
{
function
drawShadow
()
{
var
shadowLeft
=
options
.
series
.
pie
.
shadow
.
left
;
var
shadowTop
=
options
.
series
.
pie
.
shadow
.
top
;
var
edge
=
10
;
var
alpha
=
options
.
series
.
pie
.
shadow
.
alpha
;
var
radius
=
options
.
series
.
pie
.
radius
>
1
?
options
.
series
.
pie
.
radius
:
maxRadius
*
options
.
series
.
pie
.
radius
;
// set radius
if
(
options
.
series
.
pie
.
radius
>
1
)
var
radius
=
options
.
series
.
pie
.
radius
;
else
var
radius
=
maxRadius
*
options
.
series
.
pie
.
radius
;
if
(
radius
>=
(
canvasWidth
/
2
)
-
shadowLeft
||
radius
*
options
.
series
.
pie
.
tilt
>=
(
canvasHeight
/
2
)
-
shadowTop
||
radius
<=
edge
)
if
(
radius
>=
canvasWidth
/
2
-
shadowLeft
||
radius
*
options
.
series
.
pie
.
tilt
>=
canvasHeight
/
2
-
shadowTop
||
radius
<=
edge
)
{
return
;
// shadow would be outside canvas, so don't draw it
}
ctx
.
save
();
ctx
.
translate
(
shadowLeft
,
shadowTop
);
ctx
.
globalAlpha
=
alpha
;
ctx
.
fillStyle
=
'#000'
;
ctx
.
fillStyle
=
"#000"
;
// center and rotate to starting position
ctx
.
translate
(
centerLeft
,
centerTop
);
ctx
.
scale
(
1
,
options
.
series
.
pie
.
tilt
);
//radius -= edge;
for
(
var
i
=
1
;
i
<=
edge
;
i
++
)
{
for
(
var
i
=
1
;
i
<=
edge
;
i
++
)
{
ctx
.
beginPath
();
ctx
.
arc
(
0
,
0
,
radius
,
0
,
Math
.
PI
*
2
,
false
);
ctx
.
arc
(
0
,
0
,
radius
,
0
,
Math
.
PI
*
2
,
false
);
ctx
.
fill
();
radius
-=
i
;
}
...
...
@@ -350,27 +369,23 @@ More detail and specific examples can be found in the included HTML file.
ctx
.
restore
();
}
function
drawPie
()
{
var
startAngle
=
Math
.
PI
*
options
.
series
.
pie
.
startAngle
;
var
radius
;
function
drawPie
()
{
// set radius
if
(
options
.
series
.
pie
.
radius
>
1
)
radius
=
options
.
series
.
pie
.
radius
;
else
radius
=
maxRadius
*
options
.
series
.
pie
.
radius
;
var
startAngle
=
Math
.
PI
*
options
.
series
.
pie
.
startAngle
;
var
radius
=
options
.
series
.
pie
.
radius
>
1
?
options
.
series
.
pie
.
radius
:
maxRadius
*
options
.
series
.
pie
.
radius
;
// center and rotate to starting position
ctx
.
save
();
ctx
.
translate
(
centerLeft
,
centerTop
);
ctx
.
scale
(
1
,
options
.
series
.
pie
.
tilt
);
//ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
// draw slices
ctx
.
save
();
var
currentAngle
=
startAngle
;
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
{
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
{
slices
[
i
].
startAngle
=
currentAngle
;
drawSlice
(
slices
[
i
].
angle
,
slices
[
i
].
color
,
true
);
}
...
...
@@ -382,106 +397,123 @@ More detail and specific examples can be found in the included HTML file.
ctx
.
save
();
ctx
.
lineWidth
=
options
.
series
.
pie
.
stroke
.
width
;
currentAngle
=
startAngle
;
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
{
drawSlice
(
slices
[
i
].
angle
,
options
.
series
.
pie
.
stroke
.
color
,
false
);
}
ctx
.
restore
();
}
// draw donut hole
drawDonutHole
(
ctx
);
// draw labels
if
(
options
.
series
.
pie
.
label
.
show
)
if
(
options
.
series
.
pie
.
label
.
show
)
{
drawLabels
();
}
// restore to original state
ctx
.
restore
();
function
drawSlice
(
angle
,
color
,
fill
)
{
if
(
angle
<=
0
||
isNaN
(
angle
))
function
drawSlice
(
angle
,
color
,
fill
)
{
if
(
angle
<=
0
||
isNaN
(
angle
))
{
return
;
}
if
(
fill
)
if
(
fill
)
{
ctx
.
fillStyle
=
color
;
else
{
}
else
{
ctx
.
strokeStyle
=
color
;
ctx
.
lineJoin
=
'round'
;
ctx
.
lineJoin
=
"round"
;
}
ctx
.
beginPath
();
if
(
Math
.
abs
(
angle
-
Math
.
PI
*
2
)
>
0.000000001
)
ctx
.
moveTo
(
0
,
0
);
// Center of the pie
else
if
(
$
.
browser
.
msie
)
if
(
Math
.
abs
(
angle
-
Math
.
PI
*
2
)
>
0.000000001
)
{
ctx
.
moveTo
(
0
,
0
);
// Center of the pie
}
else
if
(
$
.
browser
.
msie
)
{
angle
-=
0.0001
;
//ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera
ctx
.
arc
(
0
,
0
,
radius
,
currentAngle
,
currentAngle
+
angle
,
false
);
}
//ctx.arc(0, 0, radius, 0, angle, false); // This doesn't work properly in Opera
ctx
.
arc
(
0
,
0
,
radius
,
currentAngle
,
currentAngle
+
angle
,
false
);
ctx
.
closePath
();
//ctx.rotate(angle); // This doesn't work properly in Opera
currentAngle
+=
angle
;
if
(
fill
)
if
(
fill
)
{
ctx
.
fill
();
else
}
else
{
ctx
.
stroke
();
}
}
function
drawLabels
()
{
var
currentAngle
=
startAngle
;
function
drawLabels
()
{
// set radius
if
(
options
.
series
.
pie
.
label
.
radius
>
1
)
var
radius
=
options
.
series
.
pie
.
label
.
radius
;
else
var
radius
=
maxRadius
*
options
.
series
.
pie
.
label
.
radius
;
var
currentAngle
=
startAngle
;
var
radius
=
options
.
series
.
pie
.
label
.
radius
>
1
?
options
.
series
.
pie
.
label
.
radius
:
maxRadius
*
options
.
series
.
pie
.
label
.
radius
;
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
{
if
(
slices
[
i
].
percent
>=
options
.
series
.
pie
.
label
.
threshold
*
100
)
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
{
if
(
slices
[
i
].
percent
>=
options
.
series
.
pie
.
label
.
threshold
*
100
)
{
drawLabel
(
slices
[
i
],
currentAngle
,
i
);
}
currentAngle
+=
slices
[
i
].
angle
;
}
function
drawLabel
(
slice
,
startAngle
,
index
)
{
if
(
slice
.
data
[
0
][
1
]
==
0
)
function
drawLabel
(
slice
,
startAngle
,
index
)
{
if
(
slice
.
data
[
0
][
1
]
==
0
)
{
return
;
}
// format label text
var
lf
=
options
.
legend
.
labelFormatter
,
text
,
plf
=
options
.
series
.
pie
.
label
.
formatter
;
if
(
lf
)
if
(
lf
)
{
text
=
lf
(
slice
.
label
,
slice
);
else
}
else
{
text
=
slice
.
label
;
if
(
plf
)
}
if
(
plf
)
{
text
=
plf
(
text
,
slice
);
}
var
halfAngle
=
((
startAngle
+
slice
.
angle
)
+
startAngle
)
/
2
;
var
halfAngle
=
((
startAngle
+
slice
.
angle
)
+
startAngle
)
/
2
;
var
x
=
centerLeft
+
Math
.
round
(
Math
.
cos
(
halfAngle
)
*
radius
);
var
y
=
centerTop
+
Math
.
round
(
Math
.
sin
(
halfAngle
)
*
radius
)
*
options
.
series
.
pie
.
tilt
;
var
html
=
'<span class="pieLabel" id="pieLabel'
+
index
+
'" style="position:absolute;top:'
+
y
+
'px;left:'
+
x
+
'px;">'
+
text
+
"</span>"
;
var
html
=
"<span class='pieLabel' id='pieLabel"
+
index
+
"' style='position:absolute;top:"
+
y
+
"px;left:"
+
x
+
"px;'>"
+
text
+
"</span>"
;
target
.
append
(
html
);
var
label
=
target
.
children
(
'#pieLabel'
+
index
);
var
labelTop
=
(
y
-
label
.
height
()
/
2
);
var
labelLeft
=
(
x
-
label
.
width
()
/
2
);
label
.
css
(
'top'
,
labelTop
);
label
.
css
(
'left'
,
labelLeft
);
var
label
=
target
.
children
(
"#pieLabel"
+
index
);
var
labelTop
=
(
y
-
label
.
height
()
/
2
);
var
labelLeft
=
(
x
-
label
.
width
()
/
2
);
label
.
css
(
"top"
,
labelTop
);
label
.
css
(
"left"
,
labelLeft
);
// check to make sure that the label is not outside the canvas
if
(
0
-
labelTop
>
0
||
0
-
labelLeft
>
0
||
canvasHeight
-
(
labelTop
+
label
.
height
())
<
0
||
canvasWidth
-
(
labelLeft
+
label
.
width
())
<
0
)
if
(
0
-
labelTop
>
0
||
0
-
labelLeft
>
0
||
canvasHeight
-
(
labelTop
+
label
.
height
())
<
0
||
canvasWidth
-
(
labelLeft
+
label
.
width
())
<
0
)
{
redraw
=
true
;
}
if
(
options
.
series
.
pie
.
label
.
background
.
opacity
!=
0
)
{
// put in the transparent background separately to avoid blended labels and label boxes
var
c
=
options
.
series
.
pie
.
label
.
background
.
color
;
if
(
c
==
null
)
{
c
=
slice
.
color
;
}
var
pos
=
'top:'
+
labelTop
+
'px;left:'
+
labelLeft
+
'px;'
;
$
(
'<div class="pieLabelBackground" style="position:absolute;width:'
+
label
.
width
()
+
'px;height:'
+
label
.
height
()
+
'px;'
+
pos
+
'background-color:'
+
c
+
';"> </div>'
).
insertBefore
(
label
).
css
(
'opacity'
,
options
.
series
.
pie
.
label
.
background
.
opacity
);
var
pos
=
"top:"
+
labelTop
+
"px;left:"
+
labelLeft
+
"px;"
;
$
(
"<div class='pieLabelBackground' style='position:absolute;width:"
+
label
.
width
()
+
"px;height:"
+
label
.
height
()
+
"px;"
+
pos
+
"background-color:"
+
c
+
";'></div>"
)
.
css
(
"opacity"
,
options
.
series
.
pie
.
label
.
background
.
opacity
)
.
insertBefore
(
label
);
}
}
// end individual label function
}
// end drawLabels function
...
...
@@ -489,38 +521,39 @@ More detail and specific examples can be found in the included HTML file.
}
// end draw function
// Placed here because it needs to be accessed from multiple locations
function
drawDonutHole
(
layer
)
{
// draw donut hole
if
(
options
.
series
.
pie
.
innerRadius
>
0
)
{
function
drawDonutHole
(
layer
)
{
if
(
options
.
series
.
pie
.
innerRadius
>
0
)
{
// subtract the center
layer
.
save
();
innerRadius
=
options
.
series
.
pie
.
innerRadius
>
1
?
options
.
series
.
pie
.
innerRadius
:
maxRadius
*
options
.
series
.
pie
.
innerRadius
;
layer
.
globalCompositeOperation
=
'destination-out'
;
// this does not work with excanvas, but it will fall back to using the stroke color
layer
.
globalCompositeOperation
=
"destination-out"
;
// this does not work with excanvas, but it will fall back to using the stroke color
layer
.
beginPath
();
layer
.
fillStyle
=
options
.
series
.
pie
.
stroke
.
color
;
layer
.
arc
(
0
,
0
,
innerRadius
,
0
,
Math
.
PI
*
2
,
false
);
layer
.
arc
(
0
,
0
,
innerRadius
,
0
,
Math
.
PI
*
2
,
false
);
layer
.
fill
();
layer
.
closePath
();
layer
.
restore
();
// add inner stroke
layer
.
save
();
layer
.
beginPath
();
layer
.
strokeStyle
=
options
.
series
.
pie
.
stroke
.
color
;
layer
.
arc
(
0
,
0
,
innerRadius
,
0
,
Math
.
PI
*
2
,
false
);
layer
.
arc
(
0
,
0
,
innerRadius
,
0
,
Math
.
PI
*
2
,
false
);
layer
.
stroke
();
layer
.
closePath
();
layer
.
restore
();
// TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
}
}
//-- Additional Interactive related functions --
function
isPointInPoly
(
poly
,
pt
)
{
function
isPointInPoly
(
poly
,
pt
)
{
for
(
var
c
=
false
,
i
=
-
1
,
l
=
poly
.
length
,
j
=
l
-
1
;
++
i
<
l
;
j
=
i
)
((
poly
[
i
][
1
]
<=
pt
[
1
]
&&
pt
[
1
]
<
poly
[
j
][
1
])
||
(
poly
[
j
][
1
]
<=
pt
[
1
]
&&
pt
[
1
]
<
poly
[
i
][
1
]))
&&
(
pt
[
0
]
<
(
poly
[
j
][
0
]
-
poly
[
i
][
0
])
*
(
pt
[
1
]
-
poly
[
i
][
1
])
/
(
poly
[
j
][
1
]
-
poly
[
i
][
1
])
+
poly
[
i
][
0
])
...
...
@@ -528,57 +561,67 @@ More detail and specific examples can be found in the included HTML file.
return
c
;
}
function
findNearbySlice
(
mouseX
,
mouseY
)
{
var
slices
=
plot
.
getData
(),
options
=
plot
.
getOptions
(),
radius
=
options
.
series
.
pie
.
radius
>
1
?
options
.
series
.
pie
.
radius
:
maxRadius
*
options
.
series
.
pie
.
radius
;
function
findNearbySlice
(
mouseX
,
mouseY
)
{
var
slices
=
plot
.
getData
();
var
options
=
plot
.
getOptions
();
var
radius
=
options
.
series
.
pie
.
radius
>
1
?
options
.
series
.
pie
.
radius
:
maxRadius
*
options
.
series
.
pie
.
radius
;
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
{
for
(
var
i
=
0
;
i
<
slices
.
length
;
++
i
)
{
var
s
=
slices
[
i
];
if
(
s
.
pie
.
show
)
{
if
(
s
.
pie
.
show
)
{
ctx
.
save
();
ctx
.
beginPath
();
ctx
.
moveTo
(
0
,
0
);
// Center of the pie
ctx
.
moveTo
(
0
,
0
);
// Center of the pie
//ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here.
ctx
.
arc
(
0
,
0
,
radius
,
s
.
startAngle
,
s
.
startAngle
+
s
.
angle
,
false
);
ctx
.
arc
(
0
,
0
,
radius
,
s
.
startAngle
,
s
.
startAngle
+
s
.
angle
,
false
);
ctx
.
closePath
();
x
=
mouseX
-
centerLeft
;
y
=
mouseY
-
centerTop
;
if
(
ctx
.
isPointInPath
)
{
if
(
ctx
.
isPointInPath
(
mouseX
-
centerLeft
,
mouseY
-
centerTop
))
{
//alert('found slice!');
x
=
mouseX
-
centerLeft
;
y
=
mouseY
-
centerTop
;
if
(
ctx
.
isPointInPath
)
{
if
(
ctx
.
isPointInPath
(
mouseX
-
centerLeft
,
mouseY
-
centerTop
))
{
ctx
.
restore
();
return
{
datapoint
:
[
s
.
percent
,
s
.
data
],
dataIndex
:
0
,
series
:
s
,
seriesIndex
:
i
};
}
return
{
datapoint
:
[
s
.
percent
,
s
.
data
],
dataIndex
:
0
,
series
:
s
,
seriesIndex
:
i
};
}
else
{
}
else
{
// excanvas for IE doesn;t support isPointInPath, this is a workaround.
p1X
=
(
radius
*
Math
.
cos
(
s
.
startAngle
));
p1Y
=
(
radius
*
Math
.
sin
(
s
.
startAngle
));
p2X
=
(
radius
*
Math
.
cos
(
s
.
startAngle
+
(
s
.
angle
/
4
)));
p2Y
=
(
radius
*
Math
.
sin
(
s
.
startAngle
+
(
s
.
angle
/
4
)));
p3X
=
(
radius
*
Math
.
cos
(
s
.
startAngle
+
(
s
.
angle
/
2
)));
p3Y
=
(
radius
*
Math
.
sin
(
s
.
startAngle
+
(
s
.
angle
/
2
)));
p4X
=
(
radius
*
Math
.
cos
(
s
.
startAngle
+
(
s
.
angle
/
1.5
)));
p4Y
=
(
radius
*
Math
.
sin
(
s
.
startAngle
+
(
s
.
angle
/
1.5
)));
p5X
=
(
radius
*
Math
.
cos
(
s
.
startAngle
+
s
.
angle
));
p5Y
=
(
radius
*
Math
.
sin
(
s
.
startAngle
+
s
.
angle
));
arrPoly
=
[[
0
,
0
],[
p1X
,
p1Y
],[
p2X
,
p2Y
],[
p3X
,
p3Y
],[
p4X
,
p4Y
],[
p5X
,
p5Y
]];
arrPoint
=
[
x
,
y
];
p1X
=
radius
*
Math
.
cos
(
s
.
startAngle
);
p1Y
=
radius
*
Math
.
sin
(
s
.
startAngle
);
p2X
=
radius
*
Math
.
cos
(
s
.
startAngle
+
s
.
angle
/
4
);
p2Y
=
radius
*
Math
.
sin
(
s
.
startAngle
+
s
.
angle
/
4
);
p3X
=
radius
*
Math
.
cos
(
s
.
startAngle
+
s
.
angle
/
2
);
p3Y
=
radius
*
Math
.
sin
(
s
.
startAngle
+
s
.
angle
/
2
);
p4X
=
radius
*
Math
.
cos
(
s
.
startAngle
+
s
.
angle
/
1.5
);
p4Y
=
radius
*
Math
.
sin
(
s
.
startAngle
+
s
.
angle
/
1.5
);
p5X
=
radius
*
Math
.
cos
(
s
.
startAngle
+
s
.
angle
);
p5Y
=
radius
*
Math
.
sin
(
s
.
startAngle
+
s
.
angle
);
arrPoly
=
[[
0
,
0
],
[
p1X
,
p1Y
],
[
p2X
,
p2Y
],
[
p3X
,
p3Y
],
[
p4X
,
p4Y
],
[
p5X
,
p5Y
]];
arrPoint
=
[
x
,
y
];
// TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
if
(
isPointInPoly
(
arrPoly
,
arrPoint
))
{
if
(
isPointInPoly
(
arrPoly
,
arrPoint
))
{
ctx
.
restore
();
return
{
datapoint
:
[
s
.
percent
,
s
.
data
],
dataIndex
:
0
,
series
:
s
,
seriesIndex
:
i
};
return
{
datapoint
:
[
s
.
percent
,
s
.
data
],
dataIndex
:
0
,
series
:
s
,
seriesIndex
:
i
};
}
}
ctx
.
restore
();
}
}
...
...
@@ -586,82 +629,81 @@ More detail and specific examples can be found in the included HTML file.
return
null
;
}
function
onMouseMove
(
e
)
{
triggerClickHoverEvent
(
'plothover'
,
e
);
function
onMouseMove
(
e
)
{
triggerClickHoverEvent
(
"plothover"
,
e
);
}
function
onClick
(
e
)
{
triggerClickHoverEvent
(
'plotclick'
,
e
);
function
onClick
(
e
)
{
triggerClickHoverEvent
(
"plotclick"
,
e
);
}
// trigger click or hover event (they send the same parameters so we share their code)
function
triggerClickHoverEvent
(
eventname
,
e
)
{
var
offset
=
plot
.
offset
(),
canvasX
=
parseInt
(
e
.
pageX
-
offset
.
left
),
canvasY
=
parseInt
(
e
.
pageY
-
offset
.
top
),
item
=
findNearbySlice
(
canvasX
,
canvasY
);
if
(
options
.
grid
.
autoHighlight
)
{
function
triggerClickHoverEvent
(
eventname
,
e
)
{
var
offset
=
plot
.
offset
();
var
canvasX
=
parseInt
(
e
.
pageX
-
offset
.
left
);
var
canvasY
=
parseInt
(
e
.
pageY
-
offset
.
top
);
var
item
=
findNearbySlice
(
canvasX
,
canvasY
);
if
(
options
.
grid
.
autoHighlight
)
{
// clear auto-highlights
for
(
var
i
=
0
;
i
<
highlights
.
length
;
++
i
)
{
for
(
var
i
=
0
;
i
<
highlights
.
length
;
++
i
)
{
var
h
=
highlights
[
i
];
if
(
h
.
auto
==
eventname
&&
!
(
item
&&
h
.
series
==
item
.
series
))
if
(
h
.
auto
==
eventname
&&
!
(
item
&&
h
.
series
==
item
.
series
))
{
unhighlight
(
h
.
series
);
}
}
}
// highlight the slice
if
(
item
)
if
(
item
)
{
highlight
(
item
.
series
,
eventname
);
}
// trigger any hover bind events
var
pos
=
{
pageX
:
e
.
pageX
,
pageY
:
e
.
pageY
};
target
.
trigger
(
eventname
,
[
pos
,
item
]);
target
.
trigger
(
eventname
,
[
pos
,
item
]);
}
function
highlight
(
s
,
auto
)
{
if
(
typeof
s
==
"number"
)
function
highlight
(
s
,
auto
)
{
if
(
typeof
s
==
"number"
)
{
s
=
series
[
s
];
}
var
i
=
indexOfHighlight
(
s
);
if
(
i
==
-
1
)
{
if
(
i
==
-
1
)
{
highlights
.
push
({
series
:
s
,
auto
:
auto
});
plot
.
triggerRedrawOverlay
();
}
else
if
(
!
auto
)
}
else
if
(
!
auto
)
{
highlights
[
i
].
auto
=
false
;
}
}
function
unhighlight
(
s
)
{
if
(
s
==
null
)
{
function
unhighlight
(
s
)
{
if
(
s
==
null
)
{
highlights
=
[];
plot
.
triggerRedrawOverlay
();
}
if
(
typeof
s
==
"number"
)
if
(
typeof
s
==
"number"
)
{
s
=
series
[
s
];
}
var
i
=
indexOfHighlight
(
s
);
if
(
i
!=
-
1
)
{
if
(
i
!=
-
1
)
{
highlights
.
splice
(
i
,
1
);
plot
.
triggerRedrawOverlay
();
}
}
function
indexOfHighlight
(
s
)
{
for
(
var
i
=
0
;
i
<
highlights
.
length
;
++
i
)
{
function
indexOfHighlight
(
s
)
{
for
(
var
i
=
0
;
i
<
highlights
.
length
;
++
i
)
{
var
h
=
highlights
[
i
];
if
(
h
.
series
==
s
)
return
i
;
...
...
@@ -669,11 +711,9 @@ More detail and specific examples can be found in the included HTML file.
return
-
1
;
}
function
drawOverlay
(
plot
,
octx
)
{
//alert(options.series.pie.radius);
function
drawOverlay
(
plot
,
octx
)
{
var
options
=
plot
.
getOptions
();
//alert(options.series.pie.radius);
var
radius
=
options
.
series
.
pie
.
radius
>
1
?
options
.
series
.
pie
.
radius
:
maxRadius
*
options
.
series
.
pie
.
radius
;
...
...
@@ -681,31 +721,31 @@ More detail and specific examples can be found in the included HTML file.
octx
.
translate
(
centerLeft
,
centerTop
);
octx
.
scale
(
1
,
options
.
series
.
pie
.
tilt
);
for
(
i
=
0
;
i
<
highlights
.
length
;
++
i
)
for
(
i
=
0
;
i
<
highlights
.
length
;
++
i
)
{
drawHighlight
(
highlights
[
i
].
series
);
}
drawDonutHole
(
octx
);
octx
.
restore
();
function
drawHighlight
(
series
)
{
if
(
series
.
angle
<=
0
||
isNaN
(
series
.
angle
))
function
drawHighlight
(
series
)
{
if
(
series
.
angle
<=
0
||
isNaN
(
series
.
angle
))
{
return
;
}
//octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
octx
.
fillStyle
=
"rgba(255, 255, 255, "
+
options
.
series
.
pie
.
highlight
.
opacity
+
")"
;
// this is temporary until we have access to parseColor
octx
.
fillStyle
=
"rgba(255, 255, 255, "
+
options
.
series
.
pie
.
highlight
.
opacity
+
")"
;
// this is temporary until we have access to parseColor
octx
.
beginPath
();
if
(
Math
.
abs
(
series
.
angle
-
Math
.
PI
*
2
)
>
0.000000001
)
octx
.
moveTo
(
0
,
0
);
// Center of the pie
octx
.
arc
(
0
,
0
,
radius
,
series
.
startAngle
,
series
.
startAngle
+
series
.
angle
,
false
);
if
(
Math
.
abs
(
series
.
angle
-
Math
.
PI
*
2
)
>
0.000000001
)
{
octx
.
moveTo
(
0
,
0
);
// Center of the pie
}
octx
.
arc
(
0
,
0
,
radius
,
series
.
startAngle
,
series
.
startAngle
+
series
.
angle
,
false
);
octx
.
closePath
();
octx
.
fill
();
}
}
}
// end init (plugin body)
// define pie specific options and their default values
...
...
@@ -713,8 +753,8 @@ More detail and specific examples can be found in the included HTML file.
series
:
{
pie
:
{
show
:
false
,
radius
:
'auto'
,
// actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
innerRadius
:
0
,
/* for donut */
radius
:
"auto"
,
// actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
innerRadius
:
0
,
/* for donut */
startAngle
:
3
/
2
,
tilt
:
1
,
shadow
:
{
...
...
@@ -724,16 +764,16 @@ More detail and specific examples can be found in the included HTML file.
},
offset
:
{
top
:
0
,
left
:
'auto'
left
:
"auto"
},
stroke
:
{
color
:
'#FFF'
,
color
:
"#fff"
,
width
:
1
},
label
:
{
show
:
'auto'
,
formatter
:
function
(
label
,
slice
){
return
'<div style="font-size:x-small;text-align:center;padding:2px;color:'
+
slice
.
color
+
';">'
+
label
+
'<br/>'
+
Math
.
round
(
slice
.
percent
)
+
'%</div>'
;
show
:
"auto"
,
formatter
:
function
(
label
,
slice
)
{
return
"<div style='font-size:x-small;text-align:center;padding:2px;color:"
+
slice
.
color
+
";'>"
+
label
+
"<br/>"
+
Math
.
round
(
slice
.
percent
)
+
"%</div>"
;
},
// formatter function
radius
:
1
,
// radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
background
:
{
...
...
@@ -745,10 +785,10 @@ More detail and specific examples can be found in the included HTML file.
combine
:
{
threshold
:
-
1
,
// percentage at which to combine little slices into one larger slice
color
:
null
,
// color to give the new slice (auto-generated if null)
label
:
'Other'
// label to give the new slice
label
:
"Other"
// label to give the new slice
},
highlight
:
{
//color:
'#FFF'
, // will add this functionality once parseColor is available
//color:
"#fff"
, // will add this functionality once parseColor is available
opacity
:
0.5
}
}
...
...
@@ -759,6 +799,7 @@ More detail and specific examples can be found in the included HTML file.
init
:
init
,
options
:
options
,
name
:
"pie"
,
version
:
"1.
0
"
version
:
"1.
1
"
});
})(
jQuery
);
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