Some selected previews of the examples (shown in detail further down in this document), to give you a first idea of the plugin's customizability:
25 % 30 % 40 % 45 % 55 % 65 % 100 %
1:55
80
%
20
sec.
General usage
The following examples each show a JavaScript line of the kind:
$(selector).progressPie(options)
or alternatively:
$(selector).setupProgressPie(options).progressPie()
-
The first way is usually used for a one-time drawing without dynamic updates. The second kind (setupProgressPie) stores the options, enabling you to repeatedly call the parameterless progressPie() method to redraw / update the chart with a new value but otherwise unchanged settings.
-
selector
is a jQuery selector string, depending on the actual HTML document. In these cases it's a selector specific to this actual HTML page, selecting thespan
elements corresponding to the respective example. -
The actually interesting bit is thus the
options
portion of each example. -
Please note, that these lines have to be executed after the DOM tree has been created by the browser. Typically, using jQuery, this is done in the following way:
<head> … <script type="text/javascript"> $(function() { $(selector).progressPie(options); }); </script> </head>
Default mode
$(".pp.default").progressPie();
applied to elements like:
<span class="pp default">100</span> %
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Predefined modes
Color mode (dynamic color)
$(".pp.dyncolor").progressPie({mode:$.fn.progressPie.Mode.COLOR});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Green mode (static color)
$(".pp.green").progressPie({mode:$.fn.progressPie.Mode.GREEN});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Red mode (static color)
$(".pp.red").progressPie({mode:$.fn.progressPie.Mode.RED});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Ring instead of full pie
Add the ringWidth
option in order to draw a ring segment instead of a pie.
It's recommended to combine this with either a very small strokeWidth
(defining the
stroke of the full surrounding circle)…
$(".pr.dyncolor").progressPie({mode:$.fn.progressPie.Mode.COLOR, strokeWidth: 1, ringWidth: 3});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
… or with a strokeWidth
identical to the ringWidth
but setting a different,
constant color for the outer circle's stroke via the strokeColor
option:
$(".pr.onsilver").progressPie({mode:$.fn.progressPie.Mode.COLOR, ringWidth: 4, strokeWidth: 4, strokeColor: '#ddd'});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
User-defined colors
User-defined static color (via color option)
$(".pp.navy").progressPie({color:"navy"});
$(".pp.yellow").progressPie({color:"#eee000"});
$(".pp.rgb").progressPie({color:"rgb(0,150,100)"});
$(".pp.rgba").progressPie({color:"rgba(0,150,100,0.6)"});
The following pies are each assigned one of the four classes ‘navy’, ‘yellow’, ‘rgb’, or ‘rgba’.
The option set is always the same (color
), the difference (beside from the color itself)
is the color notation syntax. The ‘rgba’ example demonstrates an alpha channel, setting a transparancy
level for the pie graph.
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Notice that the foreground pie overlaps the background circle.
In this case, using an alpha channel, i.e. semi-transparent strokes, this causes the
opacity of the doubly covered area to increase, the background circle remains visible behind
the foreground. If you don't want that, set the overlap
option (see below)
to false
:
$(".pp.rgbanooverlap").progressPie({color:"rgba(0,150,100,0.6)", overlap: false});
$(".pr.rgbanooverlap").progressPie({color:"rgba(0,150,100,0.6)", overlap: false, ringWidth: 3});
25 % 50 % 65 % 80 % 99 % 100 %
Local Color Function (via color option)
Example 1: Inline function
$(".pp.myfunc").progressPie({color:function(percent) {
return percent >= 50 ? "#3f3" : "#f33";
}});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Example 2: Function reference
function blueGt25(percent) {
var blue = percent < 25 ? 0 : (percent-25)*3; //range from 0 to 3*75 = 225 ( = max brightness for value of 100%)
return "rgb(0,0," + blue + ")";
}
…
$(function(){
$(".pp.myblue").progressPie({color:blueGt25});
});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Example 3: A function (referenced) re-using/adapting the internal function colorByPercent
function colorGt50(percent) {
var p = percent <= 50 ? 0 : 2 * (percent - 50);
return $.fn.progressPie.colorByPercent(p);
}
…
$(function(){
$(".pp.gt50").progressPie({color:colorGt50});
});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
CSS formatting
Starting with V2.0.0, the ProgressPie plug-in adds class attributes to the SVG components, enabling you to define some global CSS rules to globally format some of the pie diagram's design features instead of programmatically configuring everything via plug-in options alone: The default classnames are:
-
progresspie-background
for the background circle and -
progresspie-foreground
for the pie or ring drawn on top of the latter. -
If you are drawing a double pie/ring chart, both foreground pies or rings (outer and inner) bear the
progresspie-foreground
class, but they get (both) fitted with a second class:-
progresspie-outer
for the outer and -
progresspie-inner
for the inner pie or ring.
So a CSS rule like
.progresspie-foreground{...}
will apply to all foregrounds of single pies as well as for inner and outer displays of double pies, while a selector like.progresspie-foreground.progresspie-inner
explicitly selects all inner parts of double pies. -
-
Should you even add further values (triple pies or more), i.e. you have an outer ring containing an inner ring, which itself contains a further inner ring, which might again contain yet another inner ring and so on, the inner classes get postfixed with numbers:
-
The outer ring still gets marked class
progresspie-outer
, -
the second ring (
inner
) still gets marked by classprogresspie-inner
, -
the third ring (
inner.inner
) gets marked by classprogresspie-inner2
, -
the fourth ring (
inner.inner.inner
) gets marked by classprogresspie-inner3
. -
and so on.
-
Overriding CSS in „normal“ mode
Assume a regular plug-in call (programatically defining the colors, in this case using the predefined COLOR mode):
$(".pr.css1").progressPie({mode:$.fn.progressPie.Mode.COLOR, ringWidth: 4, strokeWidth: 4});
This example alone doesn't make any sense, since a ring segment is drawn on top of a full circle with the same
width and the same color, i.e. the ring segment will be effectively invisible.
But we can use CSS to override style properties of the chart. Here, we firstly set a stroke-dasharray
for
a dashed background circle and secondly we override the background circle's color (like we could have done locally
programatically via the strokeColor
option, see above):
.pr.css1 .progresspie-background {
stroke-dasharray: 1px 3px;
stroke: #bbb !important;
}
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Keep in mind that local styles (i.e. style
attributes inside the SVG markup generated by the plug-in)
have priority over global styles in a CSS ruleset. Since the plug-in locally sets a color via stroke
property in a style
attribute, we need to add the !important
directive in order to override
that local stroke style.
Special CSS mode
If you really want to style the color (and alignment) of your diagrams (statically) via CSS rules, you can tell the
progressPie plug-in to completely omit color and vertical-align definitions in the local styles (thus removing the need
for !important
directives).
This is done by setting the mode
option to the fourth predefined color mode:
$.fn.progressPie.Mode.CSS
.
Be aware, however, that in CSS mode…
-
you must define all colors yourself, i.e. you have to set the
stroke
andfill
properties for the background and thestroke
property for the foreground. (The foreground'sfill
property is still set locally tonone
by the ProgressPie plug-in even in CSS mode, since filling of a ring segment doesn't make sense), -
and you should define the
vertical-align
style of the SVG node, at least if the target element is not empty, but the SVG is appended or prepended to text content: The first of the following examples omits thevertical-align
rule with the result, as you can see, that the pies and the percent labels are not nicely aligned. (In any other mode, this vertical alignment is set via the plug-in'sverticalAlign
option, defaulting tobottom
, but in CSS mode, that option is ignored.
$(".pp.css1").progressPie({mode:$.fn.progressPie.Mode.CSS});
.pp.css1 .progresspie-background {
stroke-dasharray: 3px 1px;
stroke: #bbb;
fill: none;
}
.pp.css1 .progresspie-foreground {
stroke: rgba(0, 100, 150, 0.5);
}
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
$(".pr.css2").progressPie({mode:$.fn.progressPie.Mode.CSS, ringWidth: 3, strokeWidth: 3});
.pr.css2 svg {
vertical-align: bottom;
}
.pr.css2 .progresspie-background {
stroke: rgb(200, 200, 200);
fill: rgba(200, 200, 200, 0.2);
}
.pr.css2 .progresspie-foreground {
stroke: rgb(0, 200, 0);
}
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
For an example if CSS formatting double pie/ring charts see the corresponding section.
Renaming the CSS classes
The default classes progresspie-foreground
etc. have intentionally been
prefixed with "progresspie-" in order to avoid name conflicts with other CSS code.
You may globally change these defaults by overwriting the properties
jQuery.fn.progressPie.defaults.cssClassBackgroundCircle
,
jQuery.fn.progressPie.defaults.cssClassForegroundPie
,
jQuery.fn.progressPie.defaults.cssClassOuter
and jQuery.fn.progressPie.defaults.cssClassInner
.
Or you may locally set other classnames by adding the options cssClassBackgroundCircle
,
cssClassForegroundPie
, cssClassOuter
or cssClassInner
to the options argument of your plug-in call.
The following example will demonstrate this (omitting the cssClassOuter
and cssClassInner
options, since they are only used with double pies):
$(".pp.css2").progressPie({
mode: $.fn.progressPie.Mode.CSS,
strokeWidth: 0,
cssClassBackgroundCircle: "piebg",
cssClassForegroundPie: "piefg"
});
.pp.css2 svg {
vertical-align: middle;
}
.pp.css2 .piebg {
stroke-dasharray: 1,4;
fill: silver;
}
.pp.css2 .piefg {
stroke: navy
}
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Advanced options
Vertical alignment
The following example shows alternating pies with and without the option verticalAlign:"middle"
(default is "bottom")
in a line with a line-height greater than the font-size (so that alignment makes a difference).
$(".pp.vc").progressPie({verticalAlign:"middle"});
applied to elements like:
<span class="pp default">0</span>
<span class="pp vc">5</span>
…
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
append instead of prepend
By default, the pie gets prepended to the selected element's content. You may opt to appending it behind the content instead:
$(".pp.append").progressPie({prepend: false, separator: "%: "});
applied to elements like:
<span class="pp append">5</span>
0 5 25 42 50 65 80 99 100
Adding a title
Just like to HTML elements you may add a title string to a chart. Most desktop browsers will display the title as popup when the mouse cursor rest on the image for some time:
$(".pp.withTitle").progressPie({globalTitle: "Demo pie chart"});
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
The globalTitle
option adds a title to the whole (rectangular) image. Alternatively, you might use the
title
option which adds a title to the chart itself. In this case, in a desktop browser, the popup title
will only show if the mouse cursor rests on the chart's foreground, not on the transparent background regions.
You may also combine both options, in which case the title
shows on the chart's foreground, while the
globalTitle
shows on the rest of the image (i.e. the background).
The title
option is mainly intended for use on diagrams with more than one value, so each value
can get its individual title. This will be demonstrated further below in examples with three rings.
Value attribute / value data, manual size, overridden background circle's stroke (with/color) and filled background circle:
By default, the percent value to display has to be the (only) content of the selected element and the SVG graphic
gets prepended (or optionally appended) to that value (see above). But you may also provide the percent value
invisibly in an attribute of the HTML element, usually (conforming to HTML) in a data-*
attribute.
The element's content may be left empty. (If not empty, the graphic still gets prepended or appended to that content.)
The following examples demonstrate a data-attribute on an empty span element, using the valueData
option.
Also, they demonstrate different uses of the strokeWidth
and strokeColor
options which
configure the look of the surrounding circle.
And a third aspect also demonstrated is the size
option: If you don't set a size
option,
the pies will be auto-sized. If the DOM node the SVG gets prepended or appended to also contains text, the pie is auto-sized to the line-height. If the pie is be be inserted into a text-less node, this does not work and the plug-in simply chooses a
default width. By setting the size
option, you may explicitly set a size (diameter) in pixels and thus
turn off auto-sizing.
$(".pp.attr:not(.silverborder):not(.navyborder):not(.noborder):not(.ring):not(.filledCircle)").progressPie({
mode:$.fn.progressPie.Mode.COLOR, valueData:"val", size:30, strokeWidth: 5});
applied to elements like:
<span class="pp attr" data-val="0"></span>
$(".pp.attr.silverborder").progressPie({mode:$.fn.progressPie.Mode.COLOR, valueData:"val", size:30, strokeWidth: 5, strokeColor: "silver"});
strokeWidth
may also be zero:
$(".pp.attr.noborder").progressPie({mode:$.fn.progressPie.Mode.COLOR, valueData:"val", size:50, strokeWidth: 0});
If you set the strokeWidth
to the radius, i.e. half the diameter, defined by size
,
the whole background circle would effectively be filled by the background circle's strokeColor
.
This has once been recommended, but by now there are better ways for filling the background circle:
-
Firstly (since V2.0.0), you may use external CSS to define a fill color, see section on CSS formatting!
-
Secondly (since V2.1.0), you may specify the option
backgroundColor
. Just like thecolor
option this may alternatively hold a string describing a color or a function mapping a percent value to a color string.
The following example demonstrates a color constant for the background filling:
$(".pp.attr.filledCircle").progressPie({
mode:$.fn.progressPie.Mode.COLOR,
valueData:"val",
size:50,
strokeWidth: 0,
backgroundColor: "#ddd"
});
strokeWidth
1 combined with a ringWidth
and use of valueAttr
instead of valueData
and demonstration of a backgroundColor
function:
$(".pp.attr.ring").progressPie({
mode:$.fn.progressPie.Mode.COLOR,
valueAttr:"data-val",
size:30,
strokeWidth: 1,
ringWidth: 5,
backgroundColor: function(percent) {
return $.fn.progressPie.colorByPercent(percent, 0.1);
}
});
The backgroundColor
function in the example above uses the same color function as is used for the foreground color
in COLOR
mode, only adding an optional second parameter which specifies an alpha channel,
in this case set to 10% opacity (90% transparency).
Take value from form input element
Consider you're designing an HTML form for a user to fill, you might want to add a pie or ring chart
visualizing the value of an input (like a text input or a select box).
In that case, simply use the valueInput
option:
$("#inputSelect span").setupProgressPie({
valueInput: $("#inputSelect select"),
animate: true
}).progressPie();
applied to
<div id="inputSelect">
<select>
<option value="0">—</option>
<option value="20">20 %</option>
<option value="40">40 %</option>
<option value="60">60 %</option>
<option value="80">80 %</option>
<option value="100">100 %</option>
</select>
<span></span>
</div>
If the input is a simple text input, you might want to add the optionsByRawValue
option in order to define a function showing an error icon (see separate
content plug-in examples page) if an invalid
value has been entered which cannot be visualized as percent value:
$("#inputText span").setupProgressPie({
valueInput: "#inputText input",
optionsByRawValue: raw => {
let i = parseInt(raw);
return !isNaN(i) && i >= 0 && i <= 100 ? null : {
contentPlugin: "cross",
globalTitle: "Illegal input, enter number in [0..100]!"
};
}
}).progressPie();
<div id="inputText">
<input type="text" value="50" size="3">
<span></span>
</div>
The default event on which a chart update is triggered is the change
event.
On a text input, change
is fired only after defocussing the input element.
You may change that by specifying all events which should trigger an update in the
valueInputEvents
option.
The next example demonstrates this valueInputEvents
option by using a
jQuery-UI-Spinner element and adding support for the spinstop
event (besides the
default change
event) which is triggered when the user clicks on one of the
spin buttons for increasing or decreasing the value.
(Unlike the 'spin' event, the 'spinstop' event only triggers after the
spin has completed, i.e. when the value has been increased or decreased)
$("#inputSpinner span").setupProgressPie({
valueInput: $("#inputSpinner input").spinner({
min: 0,
max: 100
}),
valueInputEvents: "spinstop change",
verticalAlign: "middle",
size: 25
}).progressPie();
<div id="inputSpinner">
<input type="text" value="50" size="3">
<span></span>
</div>
Notes:
-
The
valueInput
option can only be used insetupProgressPie()
! If you call theprogressPie({…})
function directly with an options object (used only once and not stored for updates), this option will be ignored! -
The
setupProgressPie()
function, in this case, not only stores a configuration for the pie chart, but also registers an event handler on the specified input element (for the events specified byvalueInputEvents
). If you should change the setup later (by callingsetupProgressPie()
again), this event handler will not be deregistered again automatically!
Value Selector
Besides valueAttr
, valueData
and valueInput
there's
a fourth option for defining where to look up the raw value to be displayed: valueSelector
.
This is covered later on in this document.
Avoid overlapping outer stroke
If you set a different stroke color for the outer circle (see example pp.attr.silverborder
above)
or choose a semi-transparent foreground color, you'll notice that the foreground (pie or ring) has the same
radius as the background circle and thus overlaps it. You may optionally turn off that overlapping, so
that the radius of the pie or ring is the total radius of the graphic minus the outer circle's strokeWidth
.
To do so, set the overlap
option to false
(it defaults to true
).
$(".pp.attr.navyborder").progressPie({
mode:$.fn.progressPie.Mode.COLOR,
valueData:"val",
size:30,
strokeWidth: 2,
strokeColor: "navy",
overlap: false
});
See above for another example (using user-defined color with alpha channel)
In ring mode: Alignment of ring with background circle
In the previous examples showing a ring on a background circle,
we've either set ringWidth
to the same value as strokeWidth
(in which case
the ring's color has to differ from the background circle's!) or the ringWidth
has been larger
than the background circle's strokeWidth
and both strokes were aligned with their outer
sides.
You may use the ringAlign
option to change that alignment. This is only applicable,
if background circle and foreground ring are both visible (ringWidth > 0 && strokeWidth > 0
).
The meaning of the ringAlign
option depends on whether the overlap
option (see above) is true or false.
By default, overlap
is true. In this case, you can choose between three alignments
(which only make a difference if the ringWidth
is either smaller or larger than the strokeWidth
):
The default option is OUTER alignment (which has already been used in previous examples), but alternatively you may also
CENTER the smaller of the two strokes within the wider one or align both strokes on their INNER sides.
If overlap
is set to false (see above), the ringAlign
option
changes its meaning a bit: With default alignment (OUTER), the ring's OUTER side is aligned with the background circle, but
since both are not overlapping, the ring's outer side is aligned with the background circle's inner edge. Effectively
this means the ring is drawn inside of the background circle.
With the alternative INNER alignment, the ring's inner side is aligned with the outer side of the background circle.
To achieve that, the background circle is shrunk to fit inside the ring, which is effectively drawn around the background
circle on its outside. (A CENTER alignment is not defined with overlap
turned off.)
All combinations of the overlap
option and the ringAlign
option are
demonstrated in the table below. For each combination of these two options, three sets of examples
are shown, one with ringWidth < strokeWidth
, one with ringWidth === strokeWidth
and one with ringWidth > strokeWidth
.
The following code sets up all these example combinations by iterated use of the
setupProgressPie()
function: The first call sets up basic properties for all examples,
the following setups add more options to the specific examples. (Since overlap
defaults
to true
we only explicitly set the option to false in the respective examples,
and similarly, since the ringAlign
option defaults to $.fn.progressPie.RingAlign.OUTER
,
we only explicitly set that option in the examples with other alignment values.)
$(".pr.align").setupProgressPie({
mode: $.fn.progressPie.Mode.COLOR,
valueData: "val",
size: 40,
strokeColor: "#ddd",
scale: 2
});
$(".pr.align.thinner").setupProgressPie({
ringWidth: 2,
strokeWidth: 6
});
$(".pr.align.thicker").setupProgressPie({
ringWidth: 6,
strokeWidth: 2
});
$(".pr.align.same").setupProgressPie({
ringWidth: 3,
strokeWidth: 3
});
$(".pr.align.center").setupProgressPie({
ringAlign: $.fn.progressPie.RingAlign.CENTER
});
$(".pr.align.inner").setupProgressPie({
ringAlign: $.fn.progressPie.RingAlign.INNER
});
$(".pr.align.nooverlap").setupProgressPie({
overlap: false
});
$(".pr.align").progressPie();
(Hover your mouse cursor above an image in the table to see the assigned classes.)
ringAlign |
overlap: true |
overlap: false |
---|---|---|
…OUTER
(default) |
|
|
…CENTER |
|
not a valid |
…INNER |
|
|
Dashed background circle
Strokes in an SVG graphic may be dotted or dashed. The CSS section already demonstrated
the use of the stroke-dasharray
CSS property. That way you may define simple or complex
dash patterns, but you can only define the length of dashes and gaps in pixels. If you want the dashes
to be placed at certain points of the circle (e.g. draw a clock face consisting of 12 short dashes placed),
you would need to know the exact length of the circle stroke in pixels in order to calculate the correct
dasharray!
This is why the ProgressPie plug-in now also offers an option to calculate a dasharray dynamically based on the calculated circle size:
The simplest way is to just specify into how many dashes the chart's background circle should be split:
$(".pp.regulardashes").progressPie({
valueData:"val",
size:30,
strokeWidth: 2,
strokeDashes: 6
});
In this case, the dashes and the gaps between them are equally long. You may change this by additionally setting a stroke length in pixels or in percent (of the stroke's length / circumference). Only percentual settings are really independent of the pie chart's size, since they define the length in relation to the circumference. Let's demonstrate this by drawing pies of different sizes:
$(".pp.percentdashes").progressPie({
strokeWidth: 2,
strokeDashes: {
count: 8,
length: '10%'
}
});
0 5 25 33 45 50 70 80 100
To specify the length in percent, you have to
set the strokeDashes.length
option to a string literal containing a number followed
by the percent sign (see above). A single number literal would be interpreted as an abloute length in pixels!
Absolute length should only be used with manually sized pies, and you have to ensure that
strokeDashes.length * strokeDashes.count
is less than the circumference (circle stroke's length
in pixels), since the circle stroke can not be divided into parts that are (in sum) greater then the whole circle.
Also note that by default the dashes start the 12 o'clock (or 0 percent) position.
You may set the strokeDashes.centered
option to true
(it defaults to false
) in order to center the first stroke around the
12 o'clock position:
$(".pp.centereddashes").progressPie({
valueData:"val",
size:30,
strokeWidth: 2,
strokeDashes: {
count: 8,
length: '10%',
centered: true
}
});
$(".pp.clockface").progressPie({
mode: $.fn.progressPie.Mode.COLOR,
strokeColor: 'silver',
valueData: "val",
size: 30,
strokeWidth: 4,
strokeDashes: {
count: 12,
length: 2,
centered: true
}
});
You may set the strokeDashes.inverted
option to true
in order to
invert the pattern, i.e. the options count
and length
then refer to the transparent gaps, devided by (auto-adjusted) visible dashes between them:
$(".pp.clockfaceInverted").progressPie({
mode: $.fn.progressPie.Mode.COLOR,
strokeColor: 'silver',
valueData: "val",
size: 30,
strokeWidth: 4,
strokeDashes: {
count: 12,
length: 2,
centered: true,
inverted: true
}
});
Resizing relatively: sizeFactor
vs. scale
Like said above, setting the size
options disables auto-sizing and sets a new absolute size.
But you may also adjust auto-sizing by specifying the sizeFactor
option: The calculated
size (either auto-size or value of the size
option) is multiplied with this factor to get the
final size for the graphic.
The following example sets the size to 50% larger than the default size, and to emphasize the effect of relative sizing (in this case relative to font-size), each number is styled with a different font size:
$(".pp.sizefactor").progressPie({sizeFactor:1.5, verticalAlign:"middle"});
0 5 25 42 50 65 80 99 100
The sizeFactor
option is only applied to the default size (auto-size or size
) option
to calculate the diameter of the pie to draw. It has no effect on other sizes like the strokeWidth
or ringWith
options. So in the example above, the pies get larger while the strokeWidth
of the circle stays the same as it were without the sizeFactor
option.
There is a second option pretty similar, but which differs in this effect: The scale
option defines
a factor by which to resize the otherwise already rendered SVG graphic, thus resizing every aspect of the graphic
including the strokeWidth
. So if, in the example above, we replace sizeFactor
by scale
,
not only the diameter of the pies increases by 50%, but also the with of the outer circle does:
$(".pp.scale").progressPie({scale:1.5, verticalAlign:"middle"});
0 5 25 42 50 65 80 99 100
In this example of a simple pie chart, the difference between these two options is “marginal”, in more complex eamples the differences may get extremer.
If you should use “double pies” (demonstrated below), please note: Both options are “global” for outer
and inner pie and may only be set in the main options object, not inside the inner
option.
A sizeFactor
is individually applied to both graphics, outer and inner pie or ring, the
gap between an outer ring and an inner ring or pie will grow when increasing the sizeFactor
,
while scaling with the scale
option will scale outer and inner ring/pie as well the gap
between them proportionally, i.e. simply scale the whole graphic.
Value Selector
If the value should still be visible, but is not the only content of the selected element, but the content of some sub-element, you may provide a jQuery selector specifying the sub-element holding the value:
$(".pp.subelem").progressPie({mode:$.fn.progressPie.Mode.COLOR, valueSelector:".valueSub"});
applied to elements like:
<span class="pp subelem">(<span class="valueSub">0</span> %)</span>
(0 %) (5 %) (25 %) (42 %) (50 %) (65 %) (80 %) (99 %) (100 %)
Note: In the first examples, the “%” label was simply placed outside (behind) the span element holding
the value and (later) the SVG. But in some cases (e.g. for CSS styling reasons) you might prefer to bundle
static text labels and the value inside the same element and simply mark the value by wrapping it into a sub-element
like shown here.
The following example shows a special use-case for the valueSelector:
Value Selector and label displayed inside a ring with rounded ends
The following example demonstrates an application of an inner element holding the actual percent value inside the selected element. The main reason for this construct lies in the goal to display the element's content inside the ring.
Also this example demonstrates the ringEndsRounded
option.
You have two possibilities to show content inside a ring graph.
This example demonstrates the first one: Use the progressPie plug-in to simply render a ring graph
without content as SVG image and then place some HTML container with the content on top of the
image via CSS rules like those shown below.
An alternative is to use a content plug-in to render the ring content as part of the
generated SVG image. See separate content plug-in examples page
for a demonstration.
Advantages of the first alternative (HTML content on top of SVG) are easier styling of the content and that even older browsers not capable of rendering SVG images will still show the content, only the ring graph around the value would be missing.
Call of the plugin (the sequence of setupProgressPie() and progressPie() simplifies updates, see below):
$(".pr.around.percent").setupProgressPie({
size: 70,
ringWidth: 7,
strokeWidth: 0,
ringEndsRounded: true,
valueSelector: "span.value",
color: "navy"
}).progressPie();
and CSS:
.pr.around {
position: relative;
display: inline-block;
margin: 1em;
}
.pr.around span {
color: navy;
}
.pr.around span.outer {
position: absolute;
left: 0;
top: 0;
width: 70px;
text-align: center;
font-size: 10px;
padding: 15px 0;
}
.pr.around span.value {
font-size: 25px;
}
applied to elements like:
<span class="pr around percent"><span class="outer"><span class="value">0</span><br>%</span></span>
0
%
5
%
25
%
42
%
50
%
65
%
80
%
99
%
100
%
Note the option separator: ""
which avoids inserting a blank space text node between the inserted
SVG and the span.outer
.
A variation (using the same CSS code) for a one-minute countdown, with inverted dynamic color, a strokeColor
(see above) and a valueAdapter
for interpreting seconds (see below):
$(".pr.around.countdown").setupProgressPie({
size: 70,
ringWidth: 5,
strokeWidth: 5,
strokeColor: "#ddd",
strokeDashes: {
count: 12,
length: 2,
centered: true,
inverted: true
},
valueSelector: "span.value",
valueAdapter: function(s) {return parseInt(s)*10/6;},
color: function(p) {return $.fn.progressPie.colorByPercent(100-p);},
separator: ""
}).progressPie();
60
sec.
50
sec.
40
sec.
30
sec.
20
sec.
15
sec.
10
sec.
5
sec.
0
sec.
Note: Of course, you can use CSS code like in the above example not only to place the value inside the ring. You might also keep the label invisible (providing the value in a data attribute, see above) and put some other graphic (SVG or other format) over/inside the ring, e.g. a pause or stop icon clickable to halt or abort the running process whose value is displayed by the ring.
Updating (and content plug-ins)
The following examples demonstrate dynamic updating of pies or rings, using the setupProgressPie
plug-in function
which was introduced in V1.3.0: This function once sets up the options and stores them in each selected DOM node. For updating,
now all that's needed is to update the value and call the progressPie()
again, which then re-uses the same
options on each update.
The setup is usually only done once, but the #timerbutton
example below also demonstrates, that the setup may
be updated as well: In this case, the content plugin is updated to change the displayed control icon depending on the timer's state.
One of the following examples also demonstrates updating without the setupProgressPie()
method.
In this case, all the options have to be initialized again for each redraw, and the update
option
has to be set in order to enable replacing an existent graphic (using the setupProgressPie() method, the update
option automatically defaults to true).
<head>
…
<script type="text/javascript">
var timerVal = 120;
var timerRunning = false;
function startStopTimer() {
if (timerVal == 0) {
timerVal = 120;
$("#timerbutton").data("val", 0);
} else {
timerRunning = !timerRunning;
}
if (timerRunning) {
timer();
} else {
updateTimerPies();
}
}
function updateTimerPies() {
var percent = Math.floor((120 - timerVal) / 1.2);
//while progressPieSVG actually supports floating point numbers as input, these calculated percent
//values are also to be displayed inside a ring graph and are therefore intentionally truncated to integers.
$(".pp:not(.attr).timer").each(function(){
$(this).text(percent).progressPie();
});
$(".pp.attr.timer").each(function(){
$(this).data("val", percent);
//if you watch the element in the DOM inspector, you'll probably notice that the original attribute `data-val` is not changed,
//the value is stored as a number in a jQuery-internal cache (`$.cache`), not in the DOM.
//Therefore this way of updating the value requires the use of the `valueData` option, `valueAttr` will not work here!
var size = $(this).hasClass("growing") ? 30 + (percent / 2) : 30;
var strokeColor = $(this).hasClass("silverborder") ? "silver" : undefined;
$(this).progressPie({mode:$.fn.progressPie.Mode.COLOR, valueData:"val", size: size, strokeWidth: 5, strokeColor: strokeColor, update: true});
});
$(".pr.around.percent.timer").each(function(){
$("span.value", $(this)).text(percent);
}).progressPie();
if (timerVal % 2 == 0) {
$(".pr.around.countdown.timer").each(function(){
$("span.value", $(this)).text(timerVal/2);
}).progressPie();
}
$("#timerbutton").data("val", percent)
.setupProgressPie({contentPlugin: timerRunning ? "pause" : timerVal > 0 ? "play" : "stop"})
.progressPie();
}
function timer() {
if (timerRunning) {
timerVal -= 1;
if (timerVal > 0) {
window.setTimeout(timer, 500);
} else {
timerRunning = false;
}
}
updateTimerPies();
};
$(function() {
…
$("#timerbutton").setupProgressPie({
color: "#00d",
strokeWidth: 1,
ringWidth: 3,
valueData: "val",
contentPlugin: "play"
}).progressPie();
//Setup code for the other pies: see previous examples
});
</script>
</head>
…
<body>
…
<p><span class="pp default timer">0</span> %<br>
<span class="pp attr timer" data-val="0"></span><br>
<span class="pp attr silverborder timer growing" data-val="0"></span><br>
<span class="pr around percent timer"><span class="outer"><span class="value">0</span><br>%</span></span><br>
<span class="pr around countdown timer"><span class="outer"><span class="value">60</span><br>sec.</span></span><br>
<button onclick="startStopTimer()" id="timerbutton" data-val="0">Click me!</button>
</p>
…
</body>
0 %
0
%
60
sec.
The control icons in the button above are a demonstration of the SVG content plug-in mechanism: You may provide special plugin modules which render additional SVG content inside a ring graph. These control plug-ins require the inclusion of an additional JavaScript file:
<script type="text/javascript" src="js/min/jquery-progresspiesvg-controlIcons-min.js"></script>
See separate example page for more on content plug-ins!
ValueAdapters: Visualize other values than percent numbers
The following example takes a value in minutes instead of percent as a value. The valueAdapter converts any positive number of minutes into percent of an hour.
ValueAdapter functions may be used regardless of the value source: Whether the values are read from the element content (default) or from an attribute makes no difference.
$(".pp.minutes").progressPie({valueAdapter: function(valueStr) {
return parseInt(valueStr) * 10 / 6;
}})
0 5 15 20 30 35 40 45 60 80
Double / multiple pies
Taking the previous example further: The progresspie component may also display two values overlapping. This might, for example, be used to depict a countdown in hours and minutes (or minutes and seconds). The following examples both show the hours-and-minutes example in different variations. In analogy to analog watch faces, the smaller, inner pie shall display an hour value (e.g. hours of a countdown still remaining) and the outer, larger pie the minutes-of-the-hour-value.
Parsing a visible element content of pattern hh:mm
Say, you have a span element containting a time value of format "hours:minutes" like
<span class="pp hmv">6:15</span>
You might now prepend a double pie chart als follows:
$(".pp.hmv").progressPie({
mode:$.fn.progressPie.Mode.GREY,
valueAdapter: function(str) {
var m = /\d+:(\d{1,2})/.exec(str)[1];
return parseInt(m) * 10 / 6;
},
inner: {
mode:$.fn.progressPie.Mode.RED,
valueAdapter: function(str) {
var hm = /(\d+):(\d{1,2})/.exec(str);
var m = 60*parseInt(hm[1]) + parseInt(hm[2]); //hours converted to minutes plus minutes of hour = total minutes
//100% <-> 12 hours = 720 minutes
return m * 100 / 720;
}
}
});
0:00 0:15 1:00 1:55 2:45 6:15 07:58 12:15
Note that this example uses one single value string (here: the span's content, but of course
you might also use an attribute value, see above), but two valueAdapter
functions in
order to derive two different percent values from one string value. Here, this is done
using regular expressions.
Separate value attributes
Of course, if you happen to have two separate number values “at hand” you may insert these into two separate data-attributes of the HTML element and use these directly (if they happen to be percent values) or mapped via valueAdapter functions. This example uses separate attributes for hours and minutes:
<span class="pp hma" data-hours="6" data-minutes="15">6:15</span>
Also, this example demonstrates manual sizing of both the outer and the inner pie.
$(".pp.hma:not(.ring):not(.rings)").progressPie({
mode:$.fn.progressPie.Mode.RED,
valueData: "minutes",
valueAdapter: function(mins) { return mins * 10 / 6; },
size: 30,
inner: {
color: "navy",
valueData: "hours",
valueAdapter: function(hours) { return hours * 100 / 12; },
size: 20
},
verticalAlign: "middle",
strokeWidth: 1
});
0:00 0:15 1:00 1:55 2:45 6:15 7:60 12:15
Note however, that in this example the inner hour-pie is independent of the minutes pie: for the time "1:55" it fills exactly the same area (1/12) as for "1:00". The example above, on the other hand, takes advantage of the fact that the valueAdapter for the hour value also has access to the minutes value and displays for "1:55" a pie nearly as large as for "2:00" (1/6).
Combination with rings
As for single graphics, you may also set the ringWidth option for the outer and/or the inner pie. This example is simply a modification of the example above, displaying the minutes value as a ring instead of a full pie. The ringWidth is less than the difference between inner and outer radius, so that the inner pie (hour value) does fit into the ring without overlap. (Outer size is 30, inner size is 20, i.e. difference in diameter is 10, difference in radius is 5; ringWidth is set to 4, which is smaller than 5, which leaves a 1 pixel gap between inner pie and outer ring.)
$(".pp.hma.ring").progressPie({
mode:$.fn.progressPie.Mode.RED,
valueData: "minutes",
valueAdapter: function(mins) { return mins * 10 / 6; },
size: 30,
inner: {
color: "navy",
valueData: "hours",
valueAdapter: function(hours) { return hours * 100 / 12; },
size: 20
},
verticalAlign: "middle",
strokeWidth: 1,
ringWidth: 4
});
0:00 0:15 1:00 1:55 2:45 6:15 7:60 12:15
Of course, you may also apply the ringWidth option to the inner pie:
$(".pp.hma.rings").progressPie({
mode:$.fn.progressPie.Mode.RED,
valueData: "minutes",
valueAdapter: function(mins) { return mins * 10 / 6; },
size: 30,
inner: {
color: "navy",
valueData: "hours",
valueAdapter: function(hours) { return hours * 100 / 12; },
size: 20,
ringWidth: 4
},
verticalAlign: "middle",
strokeWidth: 1,
ringWidth: 4
});
0:00 0:15 1:00 1:55 2:45 6:15 7:60 12:15
Three (or more) values/rings
Starting with V2.0.0, this plug-in now supports even more than 2 pies or rings:
The inner
option may now itself contain another inner option for a third value,
that may, yet again, contain an inner option (fourth value) and so forth.
When using this feature, you should use rings instead of (overlapping) pies by setting
a ringWidth
in the main options object and in each inner object (only the innermost
might be a pie as demonstrated above for double diagrams). And you should set the size
of
each ring in order to control the spacing/gap between outer and inner ring manually for
a good result (auto-spacing doesn't work well with more than 2 values).
Also new is the support of stroke*
options even inside inner
options, i.e.
for each inner ring or pie you may draw a full circle around it or (more likely, like demonstrated below)
with strokeWidth
equal to the ringWidth
in order to draw a full
background circle overlapped by the ring.
Example with three rings, all with background circles (stroke*
), colors
configured programatically in plug-in call:
$(".triple1").progressPie({
globalTitle: "Demo with three rings",
size:50,
ringWidth: 5,
strokeWidth: 5,
color: "rgb(200, 0, 0)",
strokeColor: "rgba(200, 0, 0, 0.2)",
ringEndsRounded: true,
valueData: 'outer',
inner: {
size: 35,
ringWidth: 5,
strokeWidth: 5,
color: "rgb(0, 200, 0)",
strokeColor: "rgba(0, 200, 0, 0.2)",
ringEndsRounded: true,
valueData: 'middle',
inner: {
size: 20,
ringWidth: 5,
strokeWidth: 5,
color: 'rgb(0, 200, 200)',
strokeColor: 'rgba(0, 200, 200, 0.2)',
ringEndsRounded: true,
valueData: 'inner'
}
}
});
applied to:
<span class="triple1" data-outer="88" data-middle="45" data-inner="56"></span>
As explained above in section CSS formatting, you may, if you prefer, configure the color scheme by CSS rules instead of in the plug-in call options. A variation of the above example:
$(".triple2").progressPie({
globalTitle: "Activity charts",
title: "Move",
animate: true,
size: 60,
ringWidth: 6,
strokeWidth: 6,
mode: $.fn.progressPie.Mode.CSS,
ringEndsRounded: true,
valueData: 'outer',
inner: {
title: "Exercise",
size: 45,
mode: $.fn.progressPie.Mode.CSS,
ringWidth: 6,
strokeWidth: 6,
ringEndsRounded: true,
valueData: 'middle',
inner: {
title: "Stand",
size: 30,
mode: $.fn.progressPie.Mode.CSS,
ringWidth: 6,
strokeWidth: 6,
ringEndsRounded: true,
valueData: 'inner'
}
}
});
.triple2 {
background: black;
border-radius: 5px;
padding: 5px;
margin: 1em;
display: inline-block;
box-shadow: 0 0 5px rgba(0,0,0,0.8)
}
.triple2 svg {
vertical-align: middle;
}
.triple2 .progresspie-background {fill: none}
.triple2 .progresspie-background.progresspie-outer {stroke: rgba(220, 0, 0, 0.3)}
.triple2 .progresspie-foreground.progresspie-outer {stroke: rgb(220, 0, 0)}
.triple2 .progresspie-background.progresspie-inner {stroke: rgba(0, 220, 0, 0.3)}
.triple2 .progresspie-foreground.progresspie-inner {stroke: rgb(0, 220, 0)}
.triple2 .progresspie-background.progresspie-inner2 {stroke: rgba(0, 220, 220, 0.3)}
.triple2 .progresspie-foreground.progresspie-inner2 {stroke: rgb(0, 220, 220)}
<span class="triple2" data-outer="40" data-middle="85" data-inner="70"></span>
This example also demonstrates the use of the title
option, specifying a specific title for each of the ring, in combination with
the globalTitle
option, specifying a title for the whole chart. If, in a desktop browser, you point your mouse curser on the image and let
it rest for a while, a title popup should show either the local ring's title, if you point to a ring, or the global chart's title, if you point anywhere
else on the black background. (See Adding a title)
Note: This example uses SMIL animation (reload to play, not supported by Internet Explorer/Edge). See separate animation example page for more on that topic.
(Note 2: Obviously, this example is inspired by the activity display of the Apple Watch. It's not exactly a copy, though, just similar. Especially note that progresspieSVG does not support displaying values greater than 100%.)
See Example for optionsByRawValue
below for
another multiple-ring-example.
Rotation Animation
Note: This feature once used to be implemented by SMIL animation. SMIL Animations are supported by most modern browsers – except Microsoft's (IE or Edge). Since V2.5.0 the SMIL rotation animation has been replaced by a CSS animation. For now, this sadly does not improve browser support, since IE and Edge, while they do support CSS animation in general, don't support CSS transformations like rotation. This means, IE and Edge still don't support this rotation animation! But while SMIL support is not even intended for the future, at least Edge should support CSS transformations someday. Also, the CSS rotation can now be applied to inner pies/rings, while the old SMIL implementation only supported rotation for the outermost / main ring.
Update: With the new Feature Update for Windows 10 from April 2018, Microsoft finally added CSS transformation support for SVG to the Edge browser. I.e.: In the current Edge version, this rotation animation will now work! (Older Edge versions as well as Internet Explorer stillwon't play the animation.)
You may add a clockwise rotation animation to any pie or ring as shown above. For a normal value would not seem like a good idea, but if you want to indicate some waiting interval without the progress actually being measured at the time being, you might use this to build a “Busy-Indicator” like e.g. one of the following:
$('#rotate1').progressPie({
rotation: "500ms",
valueAdapter: function() {return 5;}
});
$('#rotate2').progressPie({
strokeWidth: 1,
ringWidth: 3,
color: "#333",
rotation: {
duration: "2s",
clockwise: false
},
valueAdapter: function() {return 50;}
});
$('#rotate3').progressPie({
strokeWidth: 0,
ringWidth: 1,
color: "navy",
rotation: true,
valueAdapter: function() {return 90;}
});
Note the valueAdapter
function in these examples, returning a constant value
defining the size of the rotating pie or the size of the gap in the rotating ring.
The animation by default only applies to the main / outer pie or ring. But the inner
option now (since V2.5.0) also supports a rotation
property, so you can animate each sub diagram
separately, as demonstrated below:
$('#rotate4').progressPie({
size: 40,
strokeWidth: 0,
ringWidth: 5,
ringEndsRounded: true,
color: "#900",
rotation: "1s",
valueAdapter: function() {return 85;},
inner: {
color: "navy",
valueData: "value",
rotation: {
duration: "5s",
clockwise: false
}
}
});
Overriding options based on percent values
Normally, you specify one set of options which gets applied regardless of the value. Most options are constant, an exception is the color: As demonstrated above, you may specify a color function setting the actual color dependent upon the percent value.
Maybe that's no enough, maybe you want to change other things dependent on the percent value, too. So, for example, you might want to show a rotaion animation (see above) as long as the percent value has not been increased yet (is still zero), but switch to a pie chart for any value greater than zero.
For static values, you might simply call the plug-in with different options depending on the static value.
The “Updating” example above also already shows a way to change other options like the size by simply calling
the progressPie plug-in with different, newly calculated options on each update.
But if you want to set up
a general rule (using the setupProgressPie
plug-in function), simply define a set of default options and add an
optionsByPercent
function, mapping a percent value to either an object with some options or to null
if the default options should not be altered for this percent value. An object returned does not have to be a complete set of options, but only
to contain those options which differ from the defaults.
The following example sets some default values for a pie chart and then overrides some options only for a value of 0% in order to then show a spinning ring instead:
function greyToGreen(percent) {
var v = percent < 50 ? 0 : percent - 50; //0..50
var rb = 100 - (2 * v);
var g = 100 + (2 * v);
return "rgb(" + rb + ", " + g + ", " + rb +")";
}
…
$(".spinThenPie").setupProgressPie({
color: greyToGreen,
strokeWidth: 2,
contentPlugin: "checkComplete", //see separate examples page for details
optionsByPercent: function(percent) {
return percent > 0 ? null : { //return null for values > 0, meaning "no changes to the defaults"
//for value 0: override strokeWith and color and add some more options
strokeWidth: 0,
ringWidth: 2,
rotation: true,
valueAdapter: function() { return 85; }, //takes the 0 value and returns 85 instead.
color: greyToGreen(0) //otherwise the color would be "greenish", calculated for the value 85
}
}
}).progressPie();
0 % 5 % 25 % 42 % 50 % 65 % 80 % 99 % 100 %
Overriding options based on raw values
Note: The following example combines several different topics, like
Double / multiple pies (see above),
content plug-ins as well as
SMIL animation.
Yet its main purpose is the demonstration of the use of the optionsByRawValue
option.
There may be cases where the calculated percent value is not suitable for deriving changes in options, but where you have to base your decision on the raw value before it gets converted into a percent value by the value adapter function.
In this case, simply use the similar optionsByRawValue
option.
But be aware that the type of the raw value (other than that of the calculated
percent value) is not guaranteed to be "number"
!
Especially when the value is read from an attribute, its type is usually
"string"
.
Just like a value adapter has to check the type and maybe convert the raw value,
so does this method!
The following example consists of two rings and one pie, all three of which deriving their individual percent values from the same raw value using different value adapters. The diagrams show a count-down. The raw value is the number of remaining seconds, which is converted into three values: hours, minutes and seconds. The inner pie's showing the total remaining time in hours (i.e. 100% filled pie represents 12 hours of remaining time or more), the ring around that shows the remaining minutes of the current hour and the outer ring the remaining seconds of the current minute—similar to an analog clock face.
In the last minute, i.e. the last 60 seconds, instead of the inner hour pie (which is already effectively empty) a content plug-in (see separate example page) is loaded which shows a numerical count-down of these 60 seconds. The decision whether to show this content plug-in or not, is easily made based on the raw value (seconds). The percent value of the outer ring (seconds) is not suitable for this decision at all, since this outer ring always shows the 100% value (60 seconds) for every full minute.
One second after the countdown reached its target (0), i.e. as soon as the raw seconds
value gets negative, the optionsByRawValue
define yet another modification
of options, removing the content plug-in again and instead showing a wait
indicator (rotating half arc). (Note that, since the raw value is allowed to be
negative, the value adapter functions for all three rings as well as the
label function for updating the hour-minute-second-label of the live pie,
explicitly test for negativeness of the raw value and return 0 in that case.)
The following code snippet not only contains the setup for the progress pie plug-in but also code for a live count-down example and the user interface to manually change the count-down value. In order not to clutter up the global scope with functions and variables specific to this example, all of them have been wrapped into an immediately invoked function expression.
(function() {
function parseSecsData(s) {
return typeof s === 'number' ? s : parseInt(s);
}
var dashes = {
count: 12,
centered: true,
length: 3,
inverted: true
};
$(".countdownHms").setupProgressPie({
globalTitle: "Countdown",
title: "Remaining seconds of current minute",
size: 60,
verticalAlign: "middle",
animate: true,
ringWidth: 2,
color: "rgb(0, 0, 200)",
strokeWidth: 2,
strokeColor: "rgba(0, 0, 200, 0.3)",
strokeDashes: dashes,
valueData: "remainingsecs",
valueAdapter: function(s) {
var totalSecs = parseSecsData(s);
var secs = totalSecs < 0 ? 0 : totalSecs % 60;
if (secs === 0 && totalSecs > 0) {
secs = 60;
}
return secs * 10 / 6; //100% = 60 secs
},
optionsByRawValue: function(s) {
var secs = parseSecsData(s);
return secs > 60 ? null : //no change if secs > 69
secs >= 0 ? { //last minute
contentPlugin: "rawValue",
contentPluginOptions: {
fontSizeFactor: 1.3
}
} : { //counter fell below zero
valueAdapter: p => 50,
rotation: true
};
},
inner: {
title: "Remaining minutes of current hour",
size: 52,
ringWidth: 5,
color: "rgb(50, 200, 150)",
animate: true,
strokeWidth: 5,
strokeColor: "rgba(50, 200, 150, 0.3)",
strokeDashes: dashes,
valueData: "remainingsecs",
valueAdapter: function(s) {
var secs = parseSecsData(s);
var p = secs < 0 ? 0 : secs % 3600 / 36; // 100% = 1h = 60min = 3600 secs
if (p === 0 && secs > 0) {
p = 100;
}
return p;
},
inner: {
title: "Remaining hours",
animate: false,
size: 38,
valueData: "remainingsecs",
valueAdapter: function(s) {
var secs = parseSecsData(s);
var mins = secs < 0 ? 0 : secs / 60;
return Math.round(mins * 10 / 72); //100% <-> 12 hours = 720 minutes
},
color: function(p) {
return $.fn.progressPie.colorByPercent(100-p);
}
}
}
}).progressPie();
function hms(s) {
const secs = s % 60;
const ms = s % 3600;
const mins = (ms - secs) / 60;
const hrs = (s - ms) / 3600;
return `${hrs}h${("0" + mins).slice(-2)}'${("0" + secs).slice(-2)}"`;
}
function tick() {
$(".countdownHms.live").each(function() {
const ctd = $(this);
let secs = ctd.data("remainingsecs");
if (secs >= 0) {
secs--;
ctd.data("remainingsecs", secs);
ctd.text(hms(Math.max(0, secs)));
ctd.progressPie();
}
});
}
window.setInterval(tick, 1000);
$("#livecountdownHmsUpdate").click(() => {
$(".countdownHms.live").data("remainingsecs", $("#livecountdownHmsInput").val());
});
})();
11h59'55" 8h55'11" 2h12'44" 1h00'01" 1h00'00"
0h01'00" 0h00'36" 0h00'01" 0h00'00" -1
Live Countdown: