jQuery Flot Chart add label per series - javascript

I am using http://www.flotcharts.org/ library to draw 2 connected series.
I can create Graph successfuly, you can see my JSFIDDLE below.
To do:
The problem is I want to add one label to the top-center of each series.
And I want to add label in such a way that if graph is resized it stays at top-center of series.
How can I do that ?
IMAGE:
JSFIDDLE:
http://jsfiddle.net/bababalcksheep/ktZ5X/2/
HTML/CSS:
html, body {height: 100%; }
JS:
var options = {
series: {
lines: { show: true,lineWidth: 2,fill: true},
points: { show: true,radius: 3,lineWidth: 1},
shadowSize: 2
},
legend: { show: false}
};
var DATA = [{
"label": "Group-1",
"data": [
[0.25, 0.25],
[0.5, 0.5],
[0.875, 0.875],
[1, 1]
]
}, {
"label": "Group-2",
"data": [
[1, 0.5],
[1.25, 0.25],
[1.5, 0.5],
[1.88, 0.875],
[2, 1]
]
}];
var plot = $.plot("#placeholder", DATA, options);

I agree with #iLikePrograms adding it in a hook event is the best approach. Here's an updated fiddle.
In your options add:
hooks: { drawSeries : [addLabel] }
Where the addLabel function is:
addLabel = function(plot, ctx, series){
var xaxis = series.xaxis;
var yaxis = series.yaxis;
// space midway on series
var x = (series.data[series.data.length-1][0] + series.data[0][0])/2;
// just below top of plot
var y = yaxis.max - (yaxis.tickSize / 2);
ctx.font = "16px 'Segoe UI'";
ctx.fillStyle = "black";
var text = series.label;
ctx.fillText(text, xaxis.p2c(x), yaxis.p2c(y)); // add the label
}

You can use the comments plugin for that. See this updated fiddle for a start.
New options:
comment: {
show: true
},
comments: [{
x: 0.625,
y: 1,
contents: "Group-1"
}, {
x: 1.5,
y: 1,
contents: "Group-2"
}]

Related

How show a circular progress chart with Plotly Javascript

I am new to using the Plotly library and this time I find myself with the need to show in Vuejs 2 a circular progress graph like the following one.
I know that plotly is very complete but I have not seen an example with a similar aspect and that is also with javascript.
Thanks in advance for any information or help you can provide.
Greetings!
With plotly Derek Example, the graph looks like this
My English is not very good, but note that the line of the circle does not have a smooth curvature.
You can use plotly.js traces and text to recreate the components of this chart. If you use a scatter to place down an array of markers, you can create the grey arc, then place the red arc over it. To calculate the coordinates of each these markers, you can center your axes at (0,0) then use x=r*cos(theta) and y=r*sin(theta) where theta is your angle in radians. You can get an array of x and y values to trace out the desired portions of the red and grey arcs.
To get the circular chart to look like yours, I set the range of the x-axes and y-axes both to [-2,2], made the radius of the circular arcs 0.9 with [0,0] as the center, set the markers for these arcs to be size 10, and made the grey arc go from 210 to 85 degrees and red arc go from 90 to -200 degrees (using the function makeArr written by mhodges in his answer here),. Then to get the green marker to display in the legend, I created a trace with a green marker but with null values so it doesn't plot anything on the chart. Text traces can be used to add text around the center of the circular arcs.
Here is an example (codepen is here):
// credit goes to mhodges: https://stackoverflow.com/a/40475362/5327068
function makeArr(startValue, stopValue, cardinality) {
var arr = [];
var step = (stopValue - startValue) / (cardinality - 1);
for (var i = 0; i < cardinality; i++) {
arr.push(startValue + (step * i));
}
return arr;
}
// The function returns two arrays of circle coordinates
// for the outer points of a circle centered at some (x,y)
// and with a radius r with an arc of theta values
function getCircleCoords(r, center, degree_values) {
var center_x=center[0]
var center_y=center[1]
var x_coords = []
var y_coords = []
for (var i = 0; i < degree_values.length; i++) {
x_coords.push(center_x + (r * Math.cos(degree_values[i]*Math.PI/180)));
y_coords.push(center_y + (r * Math.sin(degree_values[i]*Math.PI/180)));
}
return [x_coords,y_coords]
}
var trace1 = {
x: [0],
y: [0.15],
text: ['1000'],
mode: 'text',
textfont: {
family: 'arial',
size: 28,
color: 'black'
},
showlegend: false
};
var trace2 = {
x: [0],
y: [-0.15],
text: ['kW/kg'],
mode: 'text',
textfont: {
family: 'arial',
size: 22,
color: 'grey'
},
showlegend: false
};
circleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(90,-200,1000))
backgroundCircleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(210,85,1000))
// display a marker in the legend without plotting it
var trace3 = {
x: [null],
y: [null],
mode: 'markers',
marker: {color: 'green', size: 10},
name: 'Correcto funcionamiento'
};
// grey background circle
var trace4 = {
x: backgroundCircleCoords[0],
y: backgroundCircleCoords[1],
mode: 'markers',
marker: {color: '#eeeeee', size: 10},
name: null,
showlegend: false
};
// red foreground circle
var trace5 = {
x: circleCoords[0],
y: circleCoords[1],
mode: 'markers',
marker: {color: 'red', size: 10},
name: 'Funcionamiento erroneo'
};
var layout = {
title:'RelacĂ­on potencia peso',
xaxis: {
range: [-2, 2],
zeroline: false,
showgrid: false,
zeroline: false,
showline: false,
showticklabels: false
},
yaxis: {
range: [-2, 2],
showgrid: false,
zeroline: false,
showline: false,
showticklabels: false
},
width: 600,
height: 600,
legend: {
x: 0,
y: 0,
"orientation": "h"
}
};
var data = [trace1, trace2, trace3, trace4, trace5];
Plotly.newPlot('myDiv', data, layout);
EDIT: for a smoother circle, you can increase the number of markers used to draw the circle.
circleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(90,-200,5000))
backgroundCircleCoords = getCircleCoords(r=0.9, center=[0,0], radian_values=makeArr(210,85,5000))

chartjs: need color bars near yAxis scale

I would like to achieve something like the below image.
Chart with color band in yAxis
I already have working version of line chart in different places in our application. In One place we need a chart with color band in yAxis. Somehow I achieved this result StackBlitz Example
But the problems are
Not able to adjust the width of the bar
Not able to move the position of the bar close to yAxis
You can define a separate x-axis for the bar and name it "bar-x-axis" for example. The important thing is to define offset: false, ticks.display: false and gridLines.display: false.
xAxes: [{
stacked: true
},
{
id: "bar-x-axis",
offset: false,
stacked: true,
ticks: {
display: false
},
gridLines: {
display: false
}
}
]
Your bar datasets are linked to this new x-axis through the option xAxisID: "bar-x-axis" . To change the width of the bars, you would define a value between below 1 for barPercentage.
{
label: "Low-Moderate",
backgroundColor: "#ffe100",
yAxisID: "bar-y-axis",
xAxisID: "bar-x-axis",
data: [20],
barPercentage: 0.5
}
Please have a look at your amended StackBlitz.
You can draw individual boxes directly on the canvas using the Plugin Core API. The API offers a range of hooks that may be used for performing custom code.
First, you would define the color bars in an array as follows:
const colorBars = [
{ y: 20, color: "#aad700" },
{ y: 40, color: "#ffe100" },
{ y: 60, color: "#ef0000" },
{ y: 80, color: "#aad700" },
{ y: 100, color: "#ffe100" }
];
Then you can define a plugin with the beforeDraw hook as shown below:
const plugins = [
{
beforeDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales["x-axis-0"];
var yAxis = chart.scales["y-axis-0"];
ctx.save();
var prevY = 0;
colorBars.forEach((c, i) => {
ctx.fillStyle = c.color;
ctx.beginPath();
var yBottom = yAxis.getPixelForValue(prevY);
var yTop = yAxis.getPixelForValue(c.y);
ctx.fillRect(xAxis.left - 10, yTop, 10, yBottom - yTop);
ctx.stroke();
prevY = c.y;
});
ctx.restore();
}
}
];
The drawback of this solution is, that you won't see a tooltip when the mouse pointer hovers over the bars.
Please have a look at your amended StackBlitz and see how it works.

Color area between two lines based on difference

I've got a chart with two lines, and I want to color the area between them based on which line is above the other one.
This graph shows income and outcome, so if income is more than outcome then the area is green, but if the outcome is more than the income the area turns red.
I can't find a good way to do this in Highcharts. I've tried area charts, but they just color up from zero to the line.
I hope the picture illustration helps, and that someone knows how to do this.
Thanks very much.
My two data sets are just two simple arrays like for instance
let income = [0, 0, 0, 0, 1000, 1000, 2000, 5000, 9000]
let outcome = [0, 0, 0, 0, 0, 7000, 7000, 7000, 12000]
By using zones you can change color at given location along the axis you want. This is the syntax:
series: {
name: 'Income',
data: data,
zoneAxis: 'x',
zones: [{value: 1, fillColor: 'green'},
{value: 5, fillColor: 'red}
]
}
That snippet gives you two zones, green up to 1, and red from 1 to 5. Since it is not very interesting doing this manually, I made an example that does this automatically, see fiddle or bottom of post:
http://jsfiddle.net/zhjyn2o4/1/
In the end you have a arearange graph like this:
I did this in highstock, but if you prefer using highchart, then it should work using the same code, though it will look a bit different.
You might be tempted to change to areasplinerange (which looks better). But using splines it is difficult to find the intersect points, and therefore difficult to color the graph correctly.
let income = [0, 0, 0, 1000, 1000, 2000, 5000, 9000, 12000, 12000, 12000, 5000, 4000, 10000]
let outcome = [0, 0, 7000, 0, 7000, 7000, 7000, 12000, 9000, 9000, 9000, 5000, 5000, 5000]
//create a function to find where lines intersect, to color them correctly
function intersect(x1, x2, y1, y2, y3, y4) {
return ((x2 * y1 - x1 * y2) - (x2 * y3 - x1 * y4)) / ((y4 - y3) - (y2 - y1));
}
var ranges = []; //stores all the data for the graph like so [x, y1, y2]
var incomeZones = []; //stores the different zones based on where the lines intersect
var incomeBiggerBool = true; //used for keeping track of what current color is
//loop through all values in income and outcome array (assumes they are same length). Fill the ranges array and create color zones.
//Zones color up to a given point, therefore we need to push a color at the end, before it intersects
for (i = 0; i < income.length; i++) {
ranges.push([i, income[i], outcome[i]]); //push to range array
if (income[i] < outcome[i] && incomeBiggerBool) {
incomeZones.push({
value: intersect(i - 1, i, income[i - 1], income[i], outcome[i - 1], outcome[i]),
fillColor: '#C0D890', // green
}); //push to zone array
incomeBiggerBool = false;
} else if (income[i] > outcome[i] && !incomeBiggerBool) {
incomeZones.push({
value: intersect(i - 1, i, income[i - 1], income[i], outcome[i - 1], outcome[i]),
fillColor: '#ED4337' // red
}); //push to zone array
incomeBiggerBool = true;
}
}
//zones color up to a given point, therefore we need to push a color at the end as well:
if (incomeBiggerBool) {
incomeZones.push({
value: income.length,
fillColor: '#C0D890' // green
})
} else {
incomeZones.push({
value: income.length,
fillColor: '#ED4337' // red
})
}
var chart = Highcharts.stockChart('container', {
chart: {
type: 'arearange'
},
credits: {
enabled: false
},
exporting: {
enabled: false
},
rangeSelector: {
enabled: false
},
scrollbar: {
enabled: false
},
navigator: {
enabled: false
},
xAxis: {
visible: false
},
title: {
text: 'Example'
},
plotOptions: {},
tooltip: {
//Prettier tooltip:
pointFormatter: function() {
return 'Income: <b>' + this.low + '</b> - Expenditures: <b>' + this.high + '</b>'
}
},
series: [{
name: 'Income',
data: ranges,
zoneAxis: 'x',
zones: incomeZones
}]
});
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/highcharts-more.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div>

How to add an empty data point to a linechart on Chart.js?

I'm trying to add empty data points throughout a line chart using Chart.js. I have this:
var data = {
labels: [
"1","2","3","4","5","6","7","8","9","10"
],
datasets: [
{
label: "Traffic",
data: null,null,20,40,null,null,null,10,20,null
}
]
};
The problem is that the linechart only recognizes the first two "nulls" as being empty data points and doesn't display them. However, for the nulls that come after, a line (connecting the previous and next valid datapoint) is shown, which makes it seem as if the "null"-datapoints actually exist. Is there a way to NOT display null-values in linecharts? (Similar to what Canvas.js offer: http://canvasjs.com/docs/charts/basics-of-creating-html5-chart/empty-null-data-points-chart/)
I read through the Chart.js documentation and stackoverflow but could not find an answer. Can anyone help me?
I read line documentation and found a boolean option which is called spanGaps
Here's a piece of code, which i used to display this:
{
'type': 'line',
'data': {
'labels': [1, 2, 3, 4, 5],
'datasets': [{
'label': 'example',
'data': [4, 1, null, 3],
// These are style properties, there is no need to copy them
'borderColor': 'rgba(255,99,132,1)',
'borderWidth': 1,
'fill': false,
tension: 0.2,
}]
},
'options': {
spanGaps: true // this is the property I found
}
}
Chart with spanGaps = false:
Chart with spanGaps = true
Posting the summary of the answer at Line ChartJS empty / null values doesn't break the line WITH (slight) corrections for the question above
Extend the line chart
Chart.types.Line.extend({
name: "LineAlt",
draw: function () {
Chart.types.Line.prototype.draw.apply(this, arguments);
// now draw the segments
var ctx = this.chart.ctx
this.datasets.forEach(function (dataset) {
ctx.strokeStyle = dataset.strokeColor
var previousPoint = {
value: null
};
dataset.points.forEach(function (point) {
if (previousPoint.value !== null && point.value !== null) {
ctx.beginPath();
ctx.moveTo(previousPoint.x, previousPoint.y);
ctx.lineTo(point.x, point.y);
ctx.stroke();
}
previousPoint = point;
})
})
}
});
You have to call the LineAlt thus
var myLineChart = new Chart(ctx).LineAlt(data, {
datasetStrokeWidth: 0.01,
datasetFill: false,
pointDotRadius : 2,
pointDotStrokeWidth: 3
});
Other changes made for your question - data should be an array and not a comma separated set of values value
Fiddle - http://jsfiddle.net/zu3p2nky/
Edit Aug 2016
This now works out of box without the need for an extension, just be using the null as a data point.

Using different symbols for plotting data not working

I am attempting to use a different symbol for one of my data series on my flot graph as it is at a much larger scale then the rest of the data. I am using this example as reference: http://www.flotcharts.org/flot/examples/symbols/index.html
Here is what I have so far:
My includes:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.flot.js"></script>
<script type="text/javascript" src="jquery.flot.symbol.js"></script>
I then configure my flot options like so:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1},
series: { points : { show: true } }
};
I then actually plot the data:
$.plot('#placeholder', [{
data: my_data,
lines: { show : true},
points: { symbol: "square"},
color: '#CB4B4B',
label: 'My Data'
}], options);
}
However, flot is still graphing the points as the default circle. I get no error messages in firebug and I have even tried adding a logging message in the jquery.flot.symbol.js library itself to see if the "square" handler is even being called like so:
var handlers = {
square: function (ctx, x, y, radius, shadow) {
console.log("Square handler was called");
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
var size = radius * Math.sqrt(Math.PI) / 2;
ctx.rect(x - size, y - size, size + size, size + size);
},
I am getting no console messages so I am assuming the handler is not getting called correctly. Am I missing something here?
EDIT:
Example of data I am trying to plot:
var d1 = [
[1364342400000, 208],
[1364346000000, 107],
[1364353200000, 42],
[1364371200000, 1680],
[1364360400000, 52],
[1364349600000, 67],
[1364385600000, 1118],
[1364367600000, 163],
[1364382000000, 1359],
[1364378400000, 1468],
[1364389200000, 1023],
[1364356800000, 63],
[1364374800000, 1601],
[1364392800000, 556],
[1364364000000, 84],
],
d2 = [
[1364342400000, 86],
[1364346000000, 42],
[1364353200000, 13],
[1364371200000, 458],
[1364360400000, 10],
[1364349600000, 22],
[1364385600000, 453],
[1364367600000, 45],
[1364382000000, 369],
[1364378400000, 379],
[1364389200000, 358],
[1364356800000, 17],
[1364374800000, 471],
[1364392800000, 147],
[1364364000000, 16],
],
d3 = [
[1364342400000, 7],
[1364346000000, 5],
[1364382000000, 11709],
[1364371200000, 58336],
[1364360400000, 1],
[1364349600000, 1],
[1364367600000, 2],
[1364389200000, 1191],
[1364378400000, 9085],
[1364385600000, 4688],
[1364374800000, 9386],
[1364392800000, 1140],
[1364364000000, 1],
];
I have also edited my options parameter and how the plot function is called:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1}
};
$.plot("#placeholder", [{
data: d1,
lines: { show : true },
points: { show: true},
color: '#EDC240',
label: "d1"
}, {
data: d2,
lines: { show : true },
points: { show : true},
color: '#AFD8F8',
label: "d2"
}, {
data: d3,
yaxis: 2,
lines: { show : true},
points: { show: true, symbol: "square"},
color: '#CB4B4B',
label: "d3"
}], options);
I am also sure that the symbol library is being included because I have added some logging itself to the library and that is showing up fine.
I see no issue with what you've done. I made a quick working example here: http://jsfiddle.net/ryleyb/shLtU/1/
I would guess that you haven't included the symbol library (even though you say you have).
Or show your data, might somehow be an issue there (doubtful?).
This is the full flot code I ran to make a working example (plus including flot and the symbol library):
$.plot('#placeholder', [{
data: [
[1, 1],
[2, 3],
[4, 4],
[5, 9]
],
lines: {
show: true
},
points: {
show: true,
symbol: "square"
},
color: '#CB4B4B',
label: 'My Data'
}]);

Categories

Resources