Getting started¶
Note
TL,DR
let graph = new Graph( htmlDivID, someOptions );
let wave1 = graph.newWaveform().setData( yDataAsArray, xDataAsArray );
let serie = graph.newSerie('someSerieName').setWaveform( wave1 ).autoAxis();
graph.draw();
After you managed to install jsGraph and load into your browser, it’s time to display your first graph.
Graph Constructor method¶
The graph constructor takes the following possible forms
const graph = new Graph( wrapper?, options?, axes? );
where all three options are actually optional
DOM Wrapper¶
The Wrapper is the DOM element into which jsGraph will inject some SVG and HTML code. It can be the id of the container, or the html element itself:
<div id="graph-container" />
const graph = new Graph( "graph-container" );
// ...or
const container = document.getElementById( 'graph-container' );
const graph = new Graph( container );
// ...or, from jQuery
const container = $("#graph-container");
const graph = new Graph( container.get() );
You can delay the use of the wrapper and call the setWrapper
method later on:
graph.setWrapper( domWrapper );
If no width / height options are passed in the constructor, jsGraph will attempt to find out the dimension of the container, using getComputedStyle.
If it doesn’t work out, you will need to call graph.resize( widthInPx, heightInPx )
before you call the draw()
method.
Options¶
jsGraph receives a variety of options that can be set in the constructor. Most options occur with the axes or the series, but the graph itself takes a few of them. Here’s a full example of them with their default value:
const GraphOptionsDefault = {
title: '', // The title of the graph
paddingTop: 30, // Top padding, important if there's a title
paddingBottom: 5,
paddingLeft: 20,
paddingRight: 20,
// If you want to add dummy lines to make the graph appear as a rectangle
close: {
left: true,
right: true,
top: true,
bottom: true
},
// Color of the closing lines
closeColor: 'black',
// Default font size and font used for the whole graph. Can be overridden for each component
fontSize: 12,
fontFamily: 'Myriad Pro, Helvetica, Arial',
// Refer to the interaction documentation to understand those
plugins: {},
mouseActions: [],
keyActions: [],
// Where clicking somewhere on the graph unselects the shape
shapesUnselectOnClick: true,
// Whether there can be only one shape selected at the same time
shapesUniqueSelection: true,
// Axes. Continue reading to understand this syntax
axes: {}
};
Axes¶
The axes settings can also be part of the constructor. Either use them as part of the options, under the key axes
, or, for legacy reasons, as part of the third argument in the constructor.
Here’s the syntax to use:
// Do not use const, read why
let axes = {
top: [
{ /* axis definition */ },
{ /* a second top axis definition */ }
],
bottom: [],
left: [
{ /* a right axis definition */ }
],
right: []
};
jsGraph does not make a copy of this object. Also, options are pretty dynamic, so it may be that jsGraph fills those objects with internal values. This is useful when you want to dump the axis object, save it, and reload it some other time.
Axis definition¶
Here are the default options that you may override for each axis:
let axisDefault = {
// Give it a unique name to retrieve it later
name: undefined,
// Value of the axis label
labelValue: '',
// You can put false here if you decide to use the axis but not to display it
display: true,
// Flip the axis, where the high-end value is to the right or the bottom, and the low-end value to the left / top
flipped: false,
// Use this to draw a vertical or horizontal line at that value. For example, for a straight line at 0, use lineAt: 0
lineAt: false,
// Adds a certain percentage of padding to the axis, with respect to the min/max values provided by the series.
axisDataSpacing: { min: 0.1, max: 0.1 },
// This can be used to display the value differently. More on that later
unitModification: false,
// Display the primary grid, corresponding to the primary ticks (the ones with labels)
primaryGrid: true,
// Display the secondary grid, corresponding to the secondary ticks
secondaryGrid: true,
// Self-exlanatory grid styling
primaryGridWidth: 1,
primaryGridColor: '#f0f0f0',
primaryGridDasharray: undefined,
primaryGridOpacity: undefined,
primaryTicksColor: 'black',
secondaryGridWidth: 1,
secondaryGridColor: '#f0f0f0',
secondaryGridDasharray: undefined,
secondaryGridOpacity: undefined,
secondaryTicksColor: 'black',
// Use true to hide the axis when all the series associated to it are hidden
hideWhenNoSeriesShown: false,
// Offset the low-end value of the graph to 0
shiftToZero: false,
// Tick positions with respect to the axis line: TICKS_INSIDE, TICKS_CENTERED, TICKS_OUTSIDE are possibilities
tickPosition: Graph.TICKS_INSIDE,
// Approximate number of primary ticks to display on the whole axis. It is an indication that jsGraph works with, but when working with decimal values, variations can occur
nbTicksPrimary: 3,
// Approximate number of secondary ticks to display between each primary tick
nbTicksSecondary: 10,
// Use scientific scaling, where values of the ticks are displayed in the scientific notation
scientificScale: false,
// Use a value to force the scientific exponent, rather than letting jsGraph determine the best one
scientificScaleExponent: false,
// Engineering scale is similar to scientific scale, but only with exponents in multiples of 3. (ug, mg, g, kg, ...)
engineeringScale: false,
// The following three options scale the value of the ticks, when scientific scaling is off
// Scale the value of the tick by that factor. Useful for unit conversion
ticklabelratio: 1,
// Multiplies the tick values by 10^x, where x is the exponential factor
exponentialFactor: 0,
// Same as the exponentialFactor, but also applied to the label itself, when using scientific scaling
exponentialLabelFactor: 0,
// Display the axis as a log scale
logScale: false,
// Force the min and the max value. Zooming is still possible, but the min/max values provided by the series become irrelevant
forcedMin: false,
forcedMax: false,
// You can use this setting to not display the axis over the full width / height of the graph. Value in normalized percentage (0 = 0%, 1 = 100%)
span: [0, 1],
// Set the unit of the axis
unit: false,
// Wrap it in the following string
unitWrapperBefore: '',
unitWrapperAfter: '',
// Add the unit in each tick
unitInTicks: false,
// Adjust the offset between the tick and its label
tickLabelOffset: 0,
// You can display a katex formula as the label, more on this later
useKatexForLabel: false,
// Sets the upper bond that the axis can reach and disregards the value given by the series if their are higher/lower
highestMax: undefined,
lowestMin: undefined
};
Adding a serie¶
Obviously the first thing we’ll want to do is to create a new serie. But before that, we need to understand the concept of waveforms
Understanding waveforms¶
Waveforms are not much more than a suger coating over standard javascript arrays. In their more general sense they represent actual data to be plotted. However they provide a bunch of useful features which target handling the data, and therefore are independent of the serie itself, which aims to display that data.
Create a waveforms¶
Nothing simpler than creating a waveform. The Graph object exposes a shortcut to the constructor using
let waveform = Graph.newWaveform();
XY waveforms¶
XY waveforms are perhaps the most obvious one. It’s a bunch of Y data corresponding to a bunch of X data. Whether they represent scattered data or should be linked with a line is irrelevant.
Note
When used to display a line data and when it can be determined that the x values are monotoneously increasing, jsGraph decreased the rendering time by ignoring the data before the minimum bound of the x axis and the data above the maximum bound of that same axes. Obviously there are a lot more optimisation at play, but that’s just one of them…
To set the XY data to a waveform, use the setData
method:
waveform.setData( yArray, xArray );
X as a waveform¶
In this format, jsGraph actually maintains two waveforms, the main one for the y data set, and one for the x dataset. It therefore also allows you to do the following
// given xWaveform, yWaveform
xWaveform.setData( xArray );
yWaveform.setData( yArray );
yWaveform.setXWaveform( xWaveform );
xWaveform.math( /*...*/ ) // to apply math of the x data set
Y waveforms¶
Y waveforms occur when the interval between each data point is constant. The offset and scaling between the points can be set either in the constructor or using the .rescaleX
method
let wave1 = Graph.newWaveform( yDataAsArray, offset, scale );
// or
wave1.rescaleX( offset, scale );
The first y
value will be at offset
, the second at offset + scale
, the third at offset + scale * 2
, etc.
Note
A third waveform type exists: Hash waveforms. They are used to represent series that go in a bar chart (or category plot). As its name indicates, it doesn’t take (x,y)
values, but a hashmap, or more generally a javascript object:
const wave = Graph.newWaveformHash(); // Create the waveform
wave.setData({ categoryA: yVal, categoryB: yVal2 }); // Setting the data
Creating a new serie¶
To create a new serie, simply use the graph.newSerie
method:
let serie = graph.newSerie( serieName, serieOptions, serieType );
The first argument is required, while the other two are optional and default to serieOptions: {}
and serieType: Graph.SERIE_LINE
.
The serie name must be unique. If you try to use the name of an existing serie,
newSerie
will simply return the existing serie, and you may override it- The
serieType
describes which type of serie you’re trying to add. Valid values are: **
Graph.SERIE_LINE
or"line"
**Graph.SERIE_SCATTER
or"scatter"
**Graph.SERIE_CONTOUR
or"contour"
: To create contour lines **Graph.SERIE_BAR
or"bar"
: To use with bar charts **Graph.SERIE_BOX
or"box"
: Box plots **Graph.SERIE_LINE_COLORED
or"color"
: Colored line where each segment can have a different color (lower performance thanGraph.SERIE_LINE
) **Graph.SERIE_ZONE
or"zone"
: Typically used to display min/max values as a greyed area **Graph.SERIE_DENSITYMAP
: A density map (see the tutorial about how to use density maps)
- The
Hint
Most methods that apply to the series return the serie itself, allowing API calls to be chained:
let serie = graph.newSerie('name', {}, 'line').methodA().methodB().methodC();
Assigning axes to the serie¶
A serie needs to have an x and a y axis. They might not be displayed, but they must exist. Most jsGraph axis getters create axes if they don’t exist, so don’t worry too much about that. If you would like to use the default axes, use
serie.autoAxis();
// or:
serie.autoAxes();
Important
The default axes are the left
axis at index 0
and the bottom
at index 0
. They will be created automatically if they don’t exist.
You may of course use other axes. For that, the setXAxis( axis )
and setYAxis( axis )
exist:
serie.setXAxis( graph.getBottomAxis( 1 ) ); // Get the second bottom axis
serie.setYAxis( graph.getRightAxis() ); // Get the first right axisDataSpacing
// Don't do that:
serie.setXAxis( graph.getLeftAxis() ); // Error ! Assigning an y axis while the serie expects and x axis
Drawing the graph¶
So far you haven’t asked the graph to draw anything. You merely created object and told jsGraph how you wanted to render them. For the final rendering use:
graph.draw();
Boilerplate example¶
Summing up everything we’ve done, it all boils down to a few lines code. Consider the following complete example:
var g = new Graph("graph-example-gettingstarted-1", {});
g.resize(400, 300).newSerie('serieName')
.setWaveform(Graph.newWaveform().setData([1, 2, 3], [4, 5, 6]))
.autoAxis();
g.draw();
This code would display the following basic graph:
Redrawing methods¶
To redraw the method, you can rebind the data to the waveform, and the waveform to the serie:
waveform.setData( dataY, dataY ); // Rebinding arrays
serie.setWaveform( waveform ); // Rebinding waveform
graph.autoscaleAxes(); // Optional, but rescales the axes to fit the new (?) min/max values
graph.draw();
Rebinding the data is not an computationnally expensive data. However, sometimes you may loose track of dataY
and dataX
.
In this case, you can also directly mutate the arrays and not rebind them to the serie. It may be useful if you lose track of where the arrays are. That’s not a problem for jsGraph, but it becomes your responsability to tell the waveform, the serie and the graph that the data has changed.
If you’re not sure whether the min / max values have changed:
waveform.mutated(); // Tell the waveform to recompute the min/max
serie.dataHasChanged(); // Tell the serie that the data has changed
graph.updateDataMinMaxAxes(); // Tell the graph that there may be new min max values
graph.autoscaleAxes();
graph.draw();
If you are sure that the min/max values haven’t changed:
s.dataHasChanged(); // Flag the serie for a redraw
graph.draw();
Warning
Even if you do not wish to do call autoscaleAxes
, and in the case where the min/max of the data may have changed, you need to call the mutated
method on the waveform and the updateDataMinMaxAxes
on the graph object.
Demonstration¶
const graph = new Graph("graph-example-gettingstarted-2");
graph.resize(400, 300);
let x = [1, 2];
let y = [1, 2];
let w = Graph.newWaveform().setData(y, x);
let s = graph.newSerie('s').setWaveform(w).autoAxis();
graph.draw();
let i = 0;
setInterval(function () {
if (i % 100 < 50) {
x.push(i % 100 + 3);
y.push(i % 100 + 3);
} else {
x.pop();
y.pop();
}
i++;
w.mutated();
s.dataHasChanged();
graph.updateDataMinMaxAxes();
graph.autoscaleAxes();
graph.draw();
}, 200);
This code would display the following basic graph: