flot how to know the x axis points in dynamic data - javascript

I am using flot jquery library to draw charts.
when my chart has a specific number of columns, I can set the x values for my points.
but now I have a dynmic data. so how can I know the points of the x axis please?
for example,
the x axis of the first point is 1325876000000
the x axis of the second point is 1328194400000
the third is 1330360000000
the fourth is 1332838400000
but lets say that I will have 9 columns. how can I know the x axis for them please?
I am printing the chart in this way
var holder = $('#vertical-chart');
if (holder.length) {
$.plot(holder, data, chartOptions);
}
the input data is like this
label: "label1"
data: [[1325876000000,0],[1325876000000,0],[1325876000000,0],[1325876000000,30]]
but now I don't know how many points in that array. it could be 11 or it could be 2
edit
this the chartoption
chartOptions = {
xaxis: {
min: (new Date(2011, 11, 15)).getTime(),
max: (new Date(2012, 04, 18)).getTime(),
mode: "time",
tickSize: [2, "month"],
monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
tickLength: 0
},
grid: {
hoverable: true,
clickable: false,
borderWidth: 0
},
bars: {
show: true,
barWidth: 12 * 24 * 60 * 60 * 300,
fill: true,
lineWidth: 1,
order: true,
lineWidth: 0,
fillColor: { colors: [{ opacity: 1 }, { opacity: 1 }] }
},
tooltip: true,
tooltipOpts: {
content: '%s: %y'
},
colors: App.chartColors
}

When using $.plot(holder, data, chartOptions);, save the plot with a variable.
Declare var plot; globally,
and then call like this: plot = $.plot(holder, data, chartOptions);.
You can grab the data from the plot like this:
var datasets = [];
var xData = [];
datasets = plot.getData(); //this returns an array of all datasets
//goes through each series of data
for (var i = 0; i < datasets.length; i++){
//picks the series with label of "label 1"
if (datasets[i].label == "label 1"){
//copies x coordinates from the series into xData
for (var j = 0; j < datasets[i].data[j].length; j++){
xData.push(datasets[i].data[j][0]); //if you want y coords, use datasets[i].data[j][1]
}
}
}

Related

How do you plot scatter graph with chart.js

I am trying to figure out how to plot a scatter graph with chart.js the data I am trying to plot is randomly generated where dates is a list of datetime.now() objects and prices is a list of float numbers
dates = [datetime.now().strftime("%Y-%m-%d") for i in range(10)]
var dates_ = {{dates|tojson}}
var prices_ = {{prices|tojson}}
function parse_data(dates , prices)
{
console.log(dates.length , prices.length)
var tmp = [];
for (let i = 0; i < dates.length; i++)
{
var x;
var y;
tmp[i] = {x: dates.at(i), y: prices.at(i)};
}
return tmp;
}
var data_ = parse_data(dates_, prices_);
var chart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [{
lablel: "some_data",
data: data_}]
});
converting the dates to float numbers does the job but it shows the dates as number and it is not that good looking
You can define your x-axis as follows
x: {
type: 'time',
time: {
parser: 'YYYY-M-D',
unit: 'day',
displayFormats: {
day: 'D MMM YYYY'
},
tooltipFormat: 'D MMM YYYY'
}
}
Further information can be found at the Chart.js documentation here and in the Chart.js samples here.
Note that I use chartjs-adapter-moment together with moment to make this work. The formats for parsing and displaying time values as desired can be found here.
Please take a look at your amended code and see how it works.
var test = [
{ x: "2022-1-8", y: 950 },
{ x: "2022-1-9", y: 1100 },
{ x: "2022-1-10", y: 990 },
{ x: "2022-1-12", y: 1250 },
{ x: "2022-1-13", y: 1050 }
];
var chart = new Chart('chart-line', {
type: 'scatter',
data: {
datasets: [{
data: test,
label: 'buys',
borderColor: "#3e95cd"
}]
},
options: {
responsive: false,
scales: {
x: {
type: 'time',
time: {
parser: 'YYYY-M-D',
unit: 'day',
displayFormats: {
day: 'D MMM YYYY'
},
tooltipFormat: 'D MMM YYYY'
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#1.0.0"></script>
<canvas id="chart-line" height="200"></canvas>
The scatter chart uses a line chart internally but changes it so the showLine property becomes false and both axis are set to linear.
So you can just set the showLine property to false in your dataset and use a line chart.
const data = {
labels: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
datasets: [{
label: 'Dataset 1',
data: [{x:1, y:12}, {x:2, y:3}, {x:3, y:2}, {x:4, y:1}, {x:5, y:8}, {x:6, y:8}, {x:7, y:2}, {x:8, y:2}, {x:9, y:3}, {x:10, y:5}, {x:11, y:7}, {x:12, y:1}]
}]
}
const config = {
type: 'scatter',
data,
options: {
responsive: true,
maintainAspectRatio: false,
},
}
const $canvas = document.getElementById('chart')
const chart = new Chart($canvas, config)
<div class="wrapper" style="width: 98vw; height:180px">
<canvas id="chart"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>

Dynamically last 3 month Filter in Table or Graph

Right now, I manually filter the last 3 months by labels: ["JAN", "FEB", "MAR"],
I need dyanamically the last 3 months should be filtered every month. How can this be done?
This is my typescript code
HTML
<div>
<canvas id="myChart" width="400" height="300"></canvas>
</div>
TS
this.canvas = document.getElementById('myChart');
this.ctx = this.canvas.getContext('2d');
let myChart = new Chart(this.ctx, {
type: 'bar',
//type: 'doughnut',
data: {
// labels: ["Sold", "Booked", "Unsold"],
// labels: this.barchartLables,
labels: ["JAN", "FEB", "MAR"],
datasets: [{
label: 'Total Expenditure.',
//data: this.barchartdata,
data: [2517453, 2617453, 3917453],
//backgroundColor: ["red", , , , , , , , "blue"],
backgroundColor: [
'#ec6666',
'#78d1dd',
'#147ad6'
],
borderWidth: 1
}]
},
options: {
legend: {
display: false
},
responsive: false,
display: true
}
});
you can use moment js library for this purpose
like you can use moment subtract method for last any month
moment().subtract(1, 'month')//for last month
moment().subtract(2, 'month') // for second last month
moment().subtract(3, 'month') // for the third one

Chart.js - draw an arbitrary point with tooltip

I've implemented the technique described in this question to render vertical lines on my chart to show key dates when something important happened.
However, the text describing these events can be quite long, so just drawing text on the canvas isn't a good solution.
Is there some way to use the chart.js API to draw an invisible point on the chart (at the top of the line) which will become interactive and show a tooltip when the mouse hovers over it?
As far as I can see, only data points will show tooltips. I attempted to add another series to contain the lines data, but without much success - it also created a legend for this series, which I don't want. I set the values to 9999 to try to get them to appear at the top of the canvas, but this did not work and seems like a hack.
You could add a second dataset that contains a single value at the x-position where the vertical line should be drawn, its value should correspond to the highest value of the first dataset. To make the point invisible, define transparent background and border colors using 'rgba(0,0,0,0)'.
{
data: [null, null, 12],
pointRadius: 10,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)'
}
To only display the legend label of the relevant dataset, you need to define a legend.labels.filter function.
legend: {
labels: {
filter: legendItem => legendItem.datasetIndex == 0
}
},
Further we need to define some tooltip.callback functions to show desired data in the tooltips.
Please take a look at below runnable code snippet and see how it works. This code uses the latest stable version of Chart.js (currently 2.9.3).
new Chart('canvas', {
type: 'line',
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 lineAtIndex = chart.data.datasets[0].lineAtIndex;
var x = xAxis.getPixelForTick(lineAtIndex);
ctx.strokeStyle = '#ff0000';
ctx.beginPath();
ctx.moveTo(x, yAxis.bottom);
ctx.lineTo(x, yAxis.top);
ctx.stroke();
ctx.restore();
}
}],
data: {
labels: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
datasets: [{
label: 'My Dataset',
data: [12, 3, 2, 1, 8, 8, 2, 2, 3, 5, 7, 1],
lineAtIndex: 2,
lineTooltip: ['This is', 'a multi-line', 'tooltip']
},
{
data: [null, null, 12],
pointRadius: 10,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)'
}
]
},
options: {
legend: {
labels: {
filter: legendItem => legendItem.datasetIndex == 0
}
},
tooltips: {
callbacks: {
title: (tooltipItems, data) => {
if (tooltipItems[0].datasetIndex == 0) {
return data.labels[tooltipItems[0].index];
}
return data.datasets[0].lineTooltip;
},
label: (tooltipItems, data) => {
if (tooltipItems.datasetIndex == 0) {
return data.datasets[0].label + ': ' + data.datasets[0].data[tooltipItems.index];
}
return null;
}
}
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas" height="90"></canvas>

barwidth option is not working on jquery flot

I am trying to draw a line chart with bar chart. everything went well.
This is my code
$.plot(holder, [
{ data: data[0].data, lines: { show: true }, label:"Service Level" },
{ data: data[1].data, bars: { show: true }, yaxis: 2, label:"# Of Calls" } // set second series to use second axis
], {
yaxes: [{
min: 0, // options for first axis,
max: 100,
tickFormatter: function (val, axis) {
return val + '%';
}
}, {
alignTicksWithAxis: 1, // options for second axis, put it on right
position: "right"
}],
xaxis: {
min: minVal.getTime(),
max: maxVal.getTime(),
mode: "time",
timeformat: timeFormat,
//twelveHourClock: true,
tickSize: [tickVal, modeChart],
//monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
tickLength: 0
},
bars: {
barWidth: 24 * 60 * 60,
},
grid: {
hoverable: true,
clickable: false,
borderWidth: 0
},
});
}
I already set the barWidth and whatever I change the value, the width of the bar is not changing. could you help me please?
I am talking about the blue one in this image
Since your x-axis is time, the units are milliseconds. By specifying a bar width of 24*60*60 you're setting the width to be 1/1000th of a day, or about 1.5 minutes. For a chart that spans several months, 1.5 minutes is tiny and may not be what you want. If you want your bar widths to be a day, then you should specify a bar width of 24*60*60*1000 instead.
barWidth is a series option, you can specify it globally or per series:
Globally:
...
series: { // you are missing this
bars: {
barWidth: 24 * 60 * 60,
},
}
...
Per Series:
{ data: data[1].data, bars: { show: true, barWidth: 24 * 60 * 60 }, yaxis: 2, label:"# Of Calls" } // set second series to use second axis

Can I place two high charts side by side and keep the sizing dynamic?

Updated substantially to make my question more clear (I hope). I have data that I'm charting in columns to show change by year, and a sort of drill down that I'd like to put on a second X-axis to show the breakdown in the last year. If I do this:
var yearbyyear = [
[2002, 591856],
[2003, 839446],
[2004, 848463],
[2005, 1034755],
[2006, 1569442],
[2007, 1484477],
[2008, 2280282],
[2009, 3261702],
[2010, 4132972],
[2011, 5321516]
];
function createSeries(data, yAxisIndex) {
var i;
var series = [];
for (i = 0; i < data.length - 1; i++) { // Node length-1
var start = data[i];
var end = data[i + 1];
series.push({
yAxis: yAxisIndex
});
}
return series;
}
var options = {
chart: {
renderTo: 'container',
type: 'column'
},
xAxis: [{
min: 2002,
tickInterval: 1
}, {
offset: 0,
labels: false,
left: 400,
width: 100
}],
plotOptions: {
column: {
stacking: 'normal',
}
},
series: [{
xAxis: 0,
name: 'Year over Year',
data: yearbyyear
}, {
xAxis: 1,
name: 'Top Stack',
data: [2011, 2770158]
}, {
xAxis: 1,
name: 'Next Stack',
data: [2011, 2551358]
}]
};
var chart = new Highcharts.Chart(options);
The chart is fully fluid, but the series all overlap. I can keep them from overlapping, but only by giving the first chart an explicit width, and the second an x-offset to accommodate that width. Is there a way I can keep that fluidity but keep the second x-axis to the right of the first?
A commenter here pointed out that I can fudge the chart by putting the drilldown at 2012 on the same x-axis but I don't love the idea of introducing inaccuracy, even under the hood, by saying the data belongs to 2012 when it is definitely 2011 numbers.

Categories