Lines
Minimal requirements
It's very simple to create a line in the linked-charts library. There is only one required property lineFun
that defines a function of the line. So the simplest example can look like this.
var line = lc.xLine() .lineFun(function(x) {return Math.sin(x);}) .place();
As you can see, the plot is rendered in the range from 0 to 1 for both axes. These are the default values if scale domaines are not defined. But if you zoom out (use instrument panel for this), you'll see that the line is actually defined for all x values. You can use the layerDomainX
property to change the range of values for which your function is defined and domainX
and domainY
to change the original domains of both scales. More about domains you can find in this section.
Types of lines
All the lines in the linked-charts library are defined as functions that can have different form. These forms are implemented in different types of lines. The currently available are y = f(x) (xLine
), x = f(y) (yLine
), x = f(t) and y = g(t) (parametricCurve
).
xLine
xLine
charts can display functions, defined in the form y = f(x). This function should be defined on the entire range of layerDomainX
or for any real X value if this property is not defined. These lines can have only one y value for each x value and therefore you can't draw, for example, a circle with one line.
Here is a plot of the y = sin(x) function.
var line = lc.xLine() .lineFun(function(x) {return Math.sin(x);}) .domainX([0, 7]) .domainY([-1.5, 1.5]) .place();
yLine
yLine
charts can display functions, defined in the form x = f(y). This function should be defined on the entire range of layerDomainY
or for any real Y value if this property is not defined. These lines can have only one x value for each y value and therefore you can't draw, for example, a circle with one line.
Here is a plot of the x = sin(y) function.
var line = lc.yLine() .lineFun(function(x) {return Math.sin(x);}) .domainX([-1.5, 1.5]) .domainY([0, 7]) .place();
Parametric Curve
Parametric curve is defined in the form x = f(t), y = g(t). Unlike the previous two, it doesn't have the lineFun
property and utilises xFunction
and yFunction
instead. Both of these functions need to be defined inside paramRange, yet here you have more control on possible values of the parameter and so the functions may not necessary be defined for all the values from this range. See the next section for more details.
Using this type of charts, you can make lines of any shapes as soon as don't have any gaps and are finite.
Unlike xLine
and yLine
, parametricCurve
has a predefined way of estimating layerDomainX
and layerDomainY
, which are by default set to fit the entire line. Of course, this can be changed by the user, but for parametricCurve
these properties influence only the original domains of the chart's axes, not the range for which the line is defined.
Let's make some spirals.
var line = lc.parametricCurve() .xFunction(function(t) {return t * Math.sin(t * 10)}) .yFunction(function(t) {return t * Math.cos(t * 10)}) .place();
Connected points
Sometimes you don't have the function, but just want to connect some dots. Currently, in the linked-charts library there are no special types of lines for this task, but you can use [parametricCurve] and make your functions defined only for some certain values inside paramRange, by setting a specific number of steps (nsteps
).
For examle, you can set the paramRange to [0, n]
and number of steps to n
. Then you can define xFunction
and yFunction
only for integer values from 0 to n-1 and just ennumerate the dots, you want to connect.
Note that because of machine errors, values of the parameter may be not exactly integer and should be rounded.
var x = [], y = []; //generate some random set of 20 points for(var i = 0; i < 20; i++){ x.push(Math.random()); y.push(Math.random()) } var line = lc.parametricCurve() .xFunction(function(t) {return x[Math.round(t)];}) .yFunction(function(t) {return y[Math.round(t)];}) .paramRange([0, 20]) .nsteps(20) .place(); //let's add also the points lc.scatter("points", line) .x(function(k) {return x[k]}) .y(function(k) {return y[k]}); line.place_layer("points")
In this example we made a chart with two layers. One for lines and the other one for dots. You can find more information about layers here and about scatter plots here.
Multiple lines
Any line chart can have any number of lines. Each line has its own ID which is passed to lineFun
, xFunction
or yFucntion as a second argument. You can initialize several lines by setting the nelements
property (the default value is 1) or by providing an array of all the IDs via the elementIds
property. If nelements
is set to n
, then the IDs of the lines are integer numbers from 0 to n - 1.
var line = lc.xLine() .nelements(5) .lineFun(function(x, k) {return x * (k + 1);}) .domainX([0, 4]) .domainY([0, 4]) .place();
Styles
In the linked-charts library you can change colour
, opacity
, lineWidth
and dashing pattern (dasharray
) for each line in the chart. Each of these properties can be set for all the lines or for each of them separately via a callback function that gets a line ID as an argument.
var param = lc.parametricCurve() .nelements(3) .xFunction(function(t, d) { return Math.cos(t) + d; }) .yFunction(function(t, d){ return Math.sin(t); }) .colourValue(function(d) {return d.toString()}) .lineWidth(function(d) {return d;}) .dasharray(function(d) {return d;}) .paramRange([0, 2 * Math.PI]) .place();
Besides the colour
property, there is also colourValue
that in some cases can be more useful. The difference between the two is the followint. colour
is supposed to return coulour in any interpretable by CSS format. It can be name, hexademical codes, RGB format (rgb(255, 0, 0)
), but no random numbers or strings. The values of this property will be directly assigned to the stroke attribute of the lines. colourValue
accepts anything. It internally transforms its value - strings or numbers - into a colour scale that can be both continuous or categorical. You can change the palette
for this scale by setting a correspoding property.
lineWidth
is just a number that defined the width of each line.
dasharray
is a sting or number that should be valid for stroke-dasharray attribute.
var plot = lc.xLine() .lineFun(function(x) {return Math.sin(x)}) .layerDomainY([0, 10]) .colour("red"); lc.xLine("cos", plot) .lineFun(function(x) {return Math.cos(x)}) .layerDomainX([2, 3]) .colour("blue") .domainX([0, 5]) .domainY([-1, 1]) .place();
Feel free to play with chart's and layers' domains in this example.
Domains
First of all, you need to understand that each line chart is actually a layer (possibly, one of several layers) of a chart. Therefore, there is a distinction between domainX
or domainY
and layerDomainX
or layerDomainY
properties. The first ones define what domains will be actually used for the both scales, when the chart is rendered. The latter ones just used for default estimating of those scales. For xLine
and yLine
layerDomainX
and layerDomainY
respectively has also another role. The lines are defined only in this range and the line will not be displayed outside of it.
You can read more about layers and their properties here.
For domains the general rule is the following: by default layer domains are estimated so that to fit all the data of the layer and chart domains fit all the layer domains. If domains of all the layers are undefined, [0, 1]
range is used as a domain. The only two types of charts that don't have a default way of domain estimation are xLine
and yLine
. But if, for example, layerDomainX
is defined for xLine
, layerDomainY
can be estimated automatically.
Update
For any changes, you've added to the chart, to have an effect, you need first to update the chart. Each chart in the linked-charts library has an update
method, which recalculates and updates all the elements of the chart. But if you know that only some of them have been changed since the last update, you may want to change only these ones for the sake of performance time. So the update
method actually consists of several modules, each responsible for a certain type of changes. These partial updates can be called independently if necessary. The most important ones are
updateSize
- changes the size of the chart. Internally callsupdateAxes
.updateAxes
- recalculates the domains and updates both axes. Internally callsupdateElementPosition
.updateElements
- adds or removes elements to fit the current data.updateElementPosition
- updates the position of all the points of the chart.updateElementStyle
- updates colour, shape, size, etc. of all the points.