Ico is a JavaScript graph library that uses Raphaël to render graphics. This means Ico can render charts in the vast majority of modern web browsers, using VML in IE (< 9), or SVG in SVG standard-compliant web browsers such as IE 9, Firefox, Apple Safari, Google Chrome, Opera, and Konqueror for Linux. Also because Raphaël does not rely on Flash, it works well (and is tested) on iPhone.
Ico’s goal is to provide effective visual reprensentation of data according to the work of Stephen Few and Edward Tufte. In particular, Ico provides an implementation of Edward tufte’s Sparklines and Stephen Few’s Bullet Graphs.
Effective visual reprensentation of data can be achieved by following Stephen Few’s graph design considerations:
- Clarity: Use of white-space to help lend clarity to graphs, nominal scale vs. ordinal scale
- Simplicity: Minimal use of decorations and lines, reliance on the Gestalt principle of closure
- Conciseness: Avoidance of graph types that don’t efficiently present data (pie charts, radar maps)
Ico’s core provides the set of graphs and features to achieve this goal:
- Sparklines, Sparbars, and Bullet Graphs
- Line graphs
- Horizontal and Vertical Bar Graphs
This version of Ico is designed to be extensible beyond its core by providing either new graph types or new graph components. A graph component automatically becomes available to all graph types.
The original version of Ico was written by Alex Young. The current version features a new API, mainly due to componentization of many graph features, comprehensive documentation, many bug fixes, new features, most importantly implements bullet graphs, angled labels, gradient backgrounds, proper negative bar graphs rendering. For a complete list of modifications read the release notes.
To see a demonstration of the capabilities of the current version, check the current test suite in index.html.
Unfortunatly tests cannot be automated because it is primaraly about rendering in supported web browsers, most of which do not provide an API suitable for test suites. The test suite is a set of graphs showing most of Ico features. This test suite is meant to be viewed in all supported web browsers where the following tests are performed:
- scroll up and down, mouse over graphs
- zoom page, mouse over graphs
- check for font display defects such as characters mis-alignments
- measure the time to render the entire test suite page
Ico requires:
Simple sparkline, no decoration:
new Ico.SparkLine(
"market_trend_id", // DOM element where the sparkline is rendered
[5, 2, -1, 17, 23, 15, 7, 6, -5, -2, 4, 7, 3, 9] // List of values for market trend
)
Bullet graph with 3 graph background colors and gradient transtitions:
new Ico.BulletGraph(
"gross_profit_id", // DOM element where the bullet graph will be rendered
85, // Actual gross profit for current period as a percentage of gross revenues
{ // Bullet graph options
min: 0, // Minimum gross profit value
max: 100, // Maximum gross profit value
target: 65, // Forecasted gross profit value
graph_background: { // Defines graph background for gross profit
key_values: [50, 75], // Less than 50% is bad, more than 75% is good, in between is ok
key_colors: ['#555','#999','#ddd'], // The 3 colors representing the 3 quality zones
colors_transition: 10 // 10% Gradient transition between the different zones
}
}
)
Line graph with 2 lines, angled labels, $ units, meanline, mouse pointer, mouse-over value in status bar, and grid:
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
new Ico.LineGraph(
"gross_profit_id", // DOM element where the graph will be rendered
[ // The 2 series
[31, 5, 1, -5, 15, 33, 20, 25, 1, 12, 25, -3], // Drawn first
[18, -1, -7, 17, 15, 21, 1, 25, 3, 21, 16, 4] // Drawn last, on top of previous series
],
{ // Graph components' options
colors: ['#228899', '#339933' ], // Series' colors
curve_amount: 10, // Slightly curve series' lines path using Cubic Bézier
mouseover_attributes: { stroke: 'green' }, // When hovering over values
font_size: 16, // for both labels and value labels and other elements
labels: { values: months, angle: 30 }, // Set labels at a 30 degres angle
x_padding_right: 40, // Make more room on the right to properly display labels
units: '$', // $ units to display values
units_position: 0 // Render $ before values
value_labels: { // Controls value labels
marker_size: 4 // Value labels markers set to 4 pixels instead of 5
},
background: { color: '#ccf', corners: 5 }, // Set entire div background color and corner size
meanline: true, // Display mean value of all series
grid: true, // Display a grid from labels and value labels
mouse_pointer: true, // Display a cross mouse pointer in graph area
status_bar : true, // Display status bar to show values on mouse over
}
)
See index.html for more examples.
Graph classes provide defaults components appropriate for each type of graph:
Class name | Base class | Description |
---|---|---|
Ico.Base | n/a | Base class for all graphs, provides components architecture |
Ico.SparkLine | Ico.Base | Draw a single serie as a line. Expected to be rendered as an inline-block |
Ico.SparkBar | Ico.SparkLine | Draw a single serie of vertical bars. Expected to be rendered as an inline-block |
Ico.BulletGraph | Ico.Base | Draw a single value as a horizontal bar. Expected to be rendered as an inline-block |
Ico.BaseGraph | Ico.Base | Base class for more complex, multi lines and bars graphs |
Ico.LineGraph | Ico.BaseGraph | Represent series as lines |
Ico.BarGraph | Ico.BaseGraph | Vertical Bars Graph |
Ico.HorizontalBarGraph | Ico.BarGraph | Horizontal Bars Graph |
To create and render a graph, call new Ico.desired_graph_type, providing three parameters:
- The DOM element where the graph will be rendered
- Data series
- Options (optional)
Example creating and rendering a line graph:
new Ico.LineGraph( dom_element, data_series, graph_options )
The DOM element can be provided as a DOM Element object:
new Ico.LineGraph( $( "sales" ), data_series, graph_options )
The DOM element can also be specified using a string containing a DOM id:
new Ico.LineGraph( "sales", data_series, graph_options )
Data series can provided as:
- A single value (for a bullet graph only)
- An array of values for a single data serie
- An array of array of values for multiple series data
Examples:
// A single value for a bullet graph data_series = -20
// An array of values for a single serie graph data_series = [5, 2, -1, 17, 23, 15, 7, 6, -5, -2, 4, 7, 3, 9]
// An array of arrays of values for multiple series graphs data_series = [ [31, 5, 1, -5, 15, 33, 20, 25, 1, 12, 25, -3], [18, -1, -7, 17, 15, 21, 1, 25, 3, 21, 16, 4] ]
Options are provided as a hash of options where each key is the option name and each value is the option value. Options hashes can be nested typically to group options by components.
Many options are Raphaël attributes which rely on the SVG Specification so please refer to these documents when further information is needed.
Example of options:
graph_options = { // Graph components' options
colors: ['#228899', '#339933' ], // Series' colors
curve_amount: 10, // Slightly curve series' lines path using Cubic Bézier
mouseover_attributes: { stroke: 'green' }, // When hovering over values
font_size: 16, // for both labels and value labels and other elements
labels: { values: months, angle: 30 }, // Set labels at a 30 degres angle
x_padding_right: 40, // Make more room on the right to properly display labels
units: '$', // $ units to display values
units_position: 0 // Render $ before values
value_labels: { // Controls value labels
marker_size: 4 // Value labels markers set to 4 pixels instead of 5
},
background: { color: '#ccf', corners: 5 }, // Set entire div background color and corner size
meanline: true, // Display mean value of all series
grid: true, // Display a grid from labels and value labels
mouse_pointer: true, // Display a cross mouse pointer in graph area
status_bar : true, // Display status bar to show values on mouse over
}
The following are options shared by all graphs:
Option name | Default value | Description |
---|---|---|
width | DOM element width | Raphaël Canvas width |
height | DOM element height | Raphaël Canvas height |
x_padding_left | 0 pixels | Padding left of the graph array |
x_padding_right | 0 pixels | Padding right of the graph array |
y_padding_top | 0 pixels | Padding above the graph array |
y_padding_bottom | 0 pixels | Padding under the graph array |
color | DOM element color | Color for single data serie |
mouseover_attributes | see bellow | Mouseover attributes for data series |
mouseover_attributes.stroke | red | SVG stroke color |
orientation | 0 | 0: horizontal, 1:vertical |
units | Units to display with values | |
units_position | 1 | Position of units: 0 => before value, 1 => after value |
font_size | element’s font-family | Text elements font size – e.g. ‘1cm’ |
font | See below | Font attributes for all text elements |
font[‘font-family’] | element’s font-family | Font family – e.g. ‘Arial’ |
font[‘font-size’] | font_size || element font-family | Font size – e.g. ‘1cm’ |
font.fill | element’s color | Font fill – e.g. ‘blue’ |
font.stroke | ‘none’ | Font stroke color – e.g. ‘black’ |
axis | X/Y axis, true => display, hash => see ‘axis’ component option attribute |
Option name | Default value | Description |
---|---|---|
highlight | false | Higlights a value by displaying a point in sparklines or a bar in sparkbars. true => highlight last value, hash => provide additional options |
highlight.index | Index of the value to highlight, 0 => first value, null => last value | |
highlight.color | ‘red’ | Highlight color |
highlight.radius | 2 | Radius of the highlight circle, for sparklines only |
Option name | Default value | Description |
---|---|---|
min | 0 | Minimum (start) value |
max | 100 | Maximum (stop) value |
color | ‘#33e’ (blue) | Color for value bar |
target | Target rendered as a vertical line, number => target value, hash => see below | |
target.value | Target value rendered as a vertical bar | |
target.color | ‘#666’ (dark grey) | Color for target vertical bar |
target.length | 0.8 | Length of target vertical bar, <= 1 |
target[‘stroke-width’] | 2 (pixels) | Width of vertical target line |
graph_background | see Ico.Component.Graph defaults | Include graph background component, false => disable |
Ico.BaseGraph is used as a base for more complex graphs possibly with multiple series whereas sparklines and sparkbars are limited to one serie.
Ico.BaseGraph extends Ico.Base with more default features such as value_labels, focus_hint and axis enabled by default.
The following options apply as defaults for bar and Line graphs unless overrided:
Option name | Default value | Description |
---|---|---|
x_padding_left | 10 pixels | Padding left of the graph array |
x_padding_right | 20 pixels | Padding right of the graph array |
y_padding_top | 20 pixels | Padding above the graph array |
y_padding_bottom | 10 pixels | Padding under the graph array |
colors[serie_key] | Ico.Base color || Random color | Line color for serie ‘serie_key’ |
value_labels | See Component.ValueLabels | Display value labels |
focus_hint | true | Display focus hint if value labels do not start at zero. false => disable, hash => ‘focus_hint’ component options attribute |
axis | true | Display x and y axis, false => disable, hash => see ‘axis’ component option attribute |
Option name | Default value | Description |
---|---|---|
series_attributes[] | See bellow | Attributes by data series |
series_attributes[serie_key].stroke | Ico.BaseGraph colors[serie_key] | Color for line ‘serie_key’ |
series_attributes[serie_key][‘stroke-width’] | 2 pixels | Line ‘serie_key’ width |
curve_amount | 5 pixels | Cubic Bézier curve amount, 0 => disable |
dot_radius[] | 3 pixels | Radius of dots for values, 0 => no dot displayed, Array => per line values |
dot_attributes[] | See bellow | Dot attributes for all data series |
dot_attributes[serie_key][‘stroke-width’] | 1 pixel | Dot stroke width for serie_key |
dot_attributes[serie_key].stroke | Background component color || options.color[serie_key] | Dot color for serie_key |
dot_attributes[serie_key].fill | options.color | Dot fill color for serie_key |
focus_radius[] | 6 pixels | Radius of focus, 0 => disable mouse over action, Array => per line values |
focus_attributes | { stroke: ‘none’, ‘fill’: ‘white’, ‘fill-opacity’ : 0 } | Attributes hash for focus circle |
Option name | Default value | Description |
---|---|---|
series_attributes[] | See bellow | Array by data series key for bar attributes |
series_attributes[serie_key].stroke | ‘none’ | Stroke color for bar |
series_attributes[serie_key][‘stroke-width’] | 2 pixels | Stroke width for bar |
series_attributes[serie_key].gradient | gradient based on option.color or random color | Fill gradient for bar |
bar_padding | 5 pixels | Padding between bars |
bars_overlap | 1/2 | Overlapping between bars (unit fraction): 0 → no overlap, 1/1 → full overlap |
Graph features are driven by components. Each graph type defines different default components and graph orientation (horizontal or vertical) and other graph-specific options. Default components can be disabled by explicitly setting their option attribute to false.
Each component is shown with the name of its options attribute hash:
Component Class | Base Class | Option Attribute Name | Drawing Layer | Description |
---|---|---|---|---|
Ico.Component | Base class of all graph components | |||
Ico.Component.Background | Ico.Component | background | 0 | Background of the entire canvas |
Ico.Component.Grid | Ico.Component | grid | 0 | Grid |
Ico.Component.Graph | Ico.Component | graph_background | 1 | Graph area, excluding canvas padding areas, background |
Ico.Component.MousePointer | Ico.Component | mouse_pointer | 2 | Display the mouse pointer as a cross when in graph area |
Ico.Component.StatusBar | Ico.Component | status_bar | 2 | Display values on mouse over in status area |
Ico.Component.Meanline | Ico.Component | meanline | 3 | Mean line at the mean of all data values accross all series |
Ico.Component.Labels | Ico.Component | labels | 3 | Labels along the data series |
Ico.Component.ValueLabels | Ico.Component.Labels | value_labels | 4 | Label values accross data series |
Ico.Component.Axis | Ico.Component | axis | 4 | X and Y Axis |
Ico.Component.FocusHint | Ico.Component | focus_hint | 5 | Display hint if value labels do not contain zero |
Component options can be set with the following types of values:
- false => disable feature, useful when a graph type sets the option by default
- true => get default options for the component
- hash => attributes for the component
If a hash is provided and one of the options name is ‘attributes’, it is a hash of Raphaël attributes. Attribute option tables bellow define only the subset of Ico default attributes although all valid Raphaël attributes can be used.
Labels are series’ samples labels, while value labels are numerical labels associated with series’ data.
Labels are defined by the option attribute ‘labels’. If an array is provided, it reprensents the values of the labels. If more label options are provided, labels must be provided as a hash of options.
Label components always make room for themselves in the padding areas.
Values labels are always calculated. The calculation is optimized according to the following criteria:
- If zero is in the range (between min and max values), zero is always one of the value labels
- The maximum number of value labels is limited by the size of the graph area, the font, angle and orientation of the graph
- The number of labels is chosen to minimize unused areas to maximize the size of displayed data series
- The step beetween two value labels has a maximum of 2 significant digits and is a multiple of 5 if the 2 significant digits are required
- Values labels are limited to 3 significant digits using string manipulations to avoid floating-point rounding errors
- Once value labels are calculated, precision is fixed, possibly adding zeros to nicely align labels
- Finally, appropriate padding is added to make room for calculated labels using just as much space as neccesary and according to labels angle
Option name | Default value | Description |
---|---|---|
values | [1, .., # of data samples -1] | Label values, ignored for value_labels which are always calculated |
font | Ico.Base font | Label font hash |
marker_size | 5 pixels | size of labels markers, 0 => disable |
markers_attributes | See bellow | Label markers attributes hash |
markers_attributes.stroke | labels font fill | Stroke color for label markers |
markers_attributes[‘stroke-width’] | 1 pixel | Stroke width for label markers |
angle | 0 | Clockwise Angle to display labels in degrees (-90 to +90) |
grid | grid component | Grid attributes, overrides grid component |
The graph area is the area where data series are rendered. This does not include padding areas where labels and other graph features are rendered.
The graph_background option attribute, if present allows to display a grandient of colors in the graph area. The gradient is drawn along the value labels axis to add meaning to ranges of values. The default gradient meaning represents ranges where the values are ‘bad’, ‘acceptable’, and ‘good’. The actual meaning of these background colors is application-specific and the same colors could mean ‘small’, ‘average’, and ‘tall’ or any other meaning.
The graph_background attribute can be set to true to get the default background or a hash to provide specific attributes:
Option name | Default value | Description |
---|---|---|
key_colors | [‘#aaa’,‘#ccc’,‘#eee’] | Colors of the different areas of the background |
key_values | [50, 75] | Values where the transitions occur, there should be one less value than key_colors |
colors_transition | 0 | Percentage of key_values where colors transition with a gradient |
The background is the entire Raphaël canvas area.
Option name | Default value | Description |
---|---|---|
color | Background color | |
attributes | See bellow | Attribute hash for background |
attributes.stroke | ‘none’ | Stroke color |
attributes.fill | color | Fill color |
corners | Canvas height / 20 | Radius of rounded corners, 0 to disable |
If the ‘grid’ option attribute is provided it can be set to true or a hash of additional options.
All Raphaël Element Attributes are valid, only listed here are those whith default values:
Option name | Default value | Description |
---|---|---|
through | undefined | true: grid line extends to graph borders |
stroke | ‘#eee’ (very light grey) | Stroke color |
‘stroke-width’ | 1 pixel | Grid stroke width |
If the ‘axis’ option attribute is provided it can be set to true or a hash of additional options:
Option name | Default value | Description |
---|---|---|
attributes | See below | Axis attributes |
attributes.stroke | ‘#666’ (grey) | Stroke color |
attributes[‘stroke-width’] | 1 pixel | Axis stroke width |
If the ‘meanline’ attribute option is set to true or a hash of additional attributes, Ico calculates the mean of all values of all series and displays this mean value as line parallel to labels’ axis.
Option name | Default value | Description |
---|---|---|
attributes | See below | Meanline attributes |
attributes.stroke | ‘#bbb’ (light grey) | Stroke color |
attributes[‘stroke-width’] | 2 pixels | Meanline stroke width |
A focus hint is displayed as two short lines crossing the value labels axis if the value range does not include zero in order to attract the attention of the users that the graph does not start at zero nor contains zero.
Option name | Default value | Description |
---|---|---|
length | 6 pixels | Length of each focus hint line |
color | options.labels_font.fill | Hint lines color |
attributes | See below | Hint lines attributes |
attributes.stroke | color | Hint lines stroke color |
attributes[‘stroke-width’] | 2 pixels | Hint lines stroke width |
If the ‘mouse_pointer’ attribute option is set to true or a hash, a mouse pointer is displayed when the mouse is over the graph area as a cross spanning the entire width and height of the graph area.
Option name | Default value | Description |
---|---|---|
attributes | See below | Mouse Pointer attributes |
attributes.stroke | ‘#666’ (grey) | Stroke color |
attributes[‘stroke-dasharray’] | '--' |
SVG stroke pattern |
If the ‘status_bar’ attribute option is set to true or a hash, value are displayed on mouse over in the top padding area.
Option name | Default value | Description |
---|---|---|
attributes | See below | Status bar attributes |
attributes[‘text-anchor’] | ‘end’ | SVG anchor in the top padding area |
- Firefox: best compromize of quality and speed, some rendering problems of angled fonts
- IE: best angled fonts rendering, slowest by far
- Safari: fastest, bugs: while zooming
- Google Chrome: good quality, bugs: while zooming
- iPhone (Safari): pretty amazing, try it
- Opera: good fonts rendering, bugs: zoom, mouse-over while scrolling
This section outlines the projected improvements for upcoming releases.
Features:
- Display Value Labels Title either above the y axis, in the status bar or under value labels if horizontal graph
- Allow greater control of labels positioning: left-justification, top, right
- By default Draw labels on top (or right if orientation) if all values are negative
- Enable values formatting with a function to allow custom numbers formatting, provide default formatters
- Allow single axis (x or y) to be displayed
- Display values in tooltips instead of status bar, tooltips implemented w/ an external DOM library to enable out-of-the-canvas tooltips
- Zoom-in spark lines, spark bars, and bullet graphs on-mouse-over.
- Display full graph of spark lines and spark bars on mouse-click, possibly in a tooltip
- Facilitate user events definition on graph elements
- Add zero line component to draw a line at zero when zero in the range. This can be done today by adding a dummy serie but this would make it easier.
Architechture:
- Componentize series in a Ico.Serie class to allow bars and lines in the same graph but also to allow new types of data series rendering
Documentation:
- Ico box model
- methods beyond intitialization
- (for contributors) Graph and Components extensions