Draw a line around a single point in the linechart - javascript

I am creating a linechart, with months on the x axis and values on the y axis. The issue is that when there is a single data point, there is no line drawn around it. I was able to draw a horizontal line using the annotations plugin but when the value is > 0 i dont know how to draw a line then, since it is supposed to be a curve.
export const optionsMap = () => ({
maintainAspectRatio: false,
responsive: true,
legend: {
display: false
},
elements: {
topLabel: {}
},
layout: {
padding: {
top: 150,
right: 45,
left: 40,
bottom: 5,
}
},
plugins: {
centerText: false,
datalabels: false,
},
annotation: {
drawTime: 'beforeDatasetsDraw',
annotations: [
{
type: 'line',
scaleID: 'y-axis-0',
value: 0.01,
mode: "horizontal",
borderColor: "#347aeb",
borderWidth: 2,
backgroundColor: "rgba(255, 0, 0, 0.3)"
}
]
}
});

I have found a solution, hope this helps someone.
Basically we can add sample points around the single data point we have. I made a function which basically pads sample points in order to draw a line around it.
/**
*
* The data points needed to draw a chart around
* a single point.
*/
const padDataPoints = (data, padValue) => {
for (let i = 0; i < padValue; i++) {
data.push(0);
data.unshift(0);
}
}
This is a simple function which adds padding points on either side of the data point.
We can then make the points disappear in chart js, by making the pointRadius of all the padding points as zero.

Related

Create bar chart with chart.js where space per bar is the same, overall chart size adjusted

Here are my Javascript options and two screenshots showing examples of charts I've created. The width of the bars is set to 50 pixels. But the overall size of the chart is the same, even though one chart has two bars and the other five. This means the chart with five bars is squeezed tighter than the one with two, even though the actual bars are all 50 pixels. I'm looking for more consistency between these two charts, so that the one with only two bars would be a much "shorter" chart overall, with spacing to match the one with five bars. Is this possible with chart.js?
options: {
aspectRatio: 3,
legend: {
display: false
},
scales: {
xAxes: [{
barThickness: 50,
ticks: {
beginAtZero: true,
suggestedMax: maxAxisX
}
}],
yAxes: [{
maxBarThickness: 50,
ticks: {
beginAtZero: true
}
}]
}
}
The Plugin Core API offers a range of hooks that may be used for performing custom code. You can use the beforeRender hook to define the height of the canvas parent div depending on the number of bars contained in the chart. This function must also consider the space needed on top and below the chart, especially for drawing the xAxis ticks.
plugins: [{
beforeRender: chart => {
if (!chart.config.options.nonChartAreaHeight) {
var yAxis = chart.scales['y-axis-0'];
chart.config.options.nonChartAreaHeight = chart.chart.height - (yAxis.bottom - yAxis.top);
}
const barThickness = chart.config.data.datasets[0].barThickness;
const chartAreaHeight = (chart.config.data.labels.length * barThickness * 2);
document.getElementById("chartWrapper").style.height = (chartAreaHeight + chart.config.options.nonChartAreaHeight) + 'px';
}
}],
Please note that instead of defining the option aspectRatio, we need to define maintainAspectRatio: false.
Please have a look at the code sample below that produces two charts. This solution uses the latest stable version of Chart.js (2.9.3).
new Chart('myChart', {
type: 'horizontalBar',
plugins: [{
beforeRender : chart => {
if (!chart.config.options.nonChartAreaHeight) {
var yAxis = chart.scales['y-axis-0'];
chart.config.options.nonChartAreaHeight = chart.chart.height - (yAxis.bottom - yAxis.top);
}
const barThickness = chart.config.data.datasets[0].barThickness;
const chartAreaHeight = (chart.config.data.labels.length * barThickness * 2);
document.getElementById("chartWrapper").style.height = (chartAreaHeight + chart.config.options.nonChartAreaHeight) + 'px';
}
}],
data: {
labels: ['1', '2', '3', '4'],
datasets: [{
barThickness: 20,
data: [100, 90, 80, 70]
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
div {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<div id="chartWrapper">
<canvas id="myChart"></canvas>
</div>

How to stop Flot Charts from re-ordering my data?

I am using a line chart. I feed the data the following:
var scheduled = [[51,1700],[52, 1750],[1,1600],[2,1675]];
var actual = [[51,1320],[52, 1550],[1,1575],[2,1600]];
In the above the first number of each set is the week of the year and I am trying to show the last 4 months of data.
However, when the chart is drawn Flot charts re-sorts the data by the first value (lowest to highest) which creates all kinds of issues. Instead of 4 columns in the series there are now 52, and the lines are quite out of whack.
I don't see anything in the documentation that says this is supposed to happen, nor do I see anything that says I can prevent it. However, for the data to be meaningful, the data must not be re-ordered.
Is there a setting I'm unaware of that can stop this behavior?
Edit : Adding plot code
var plot = $.plot('#scheduled-actual-flot-line', [
{
label: 'Scheduled Hours',
data: scheduled,
lines: { show: true, lineWidth: 2, fill: true, fillColor: { colors: [{ opacity: 0.5 }, { opacity: 0.5 }] } },
points: { show: true, radius: 4 }
},
{
label: 'Actual Hours',
data: actual,
lines: { show: true, lineWidth: 2, fill: true, fillColor: { colors: [{ opacity: 0.5 }, { opacity: 0.5 }] } },
points: { show: true, radius: 4 }
}],
{
series: {
lines: { show: true },
points: { show: true },
shadowSize: 0 // Drawing is faster without shadows
},
colors: ['#afd2f0', '#177bbb'],
legend: {
show: true,
position: 'nw',
margin: [15, 0]
},
grid: {
borderWidth: 0,
hoverable: true,
clickable: true
},
yaxis: { ticks: 4, tickColor: '#eeeeee' },
xaxis: { ticks: 12, tickColor: '#ffffff' }
}
);
Flot takes the x values as numbers and displays / sorts them accordingly. If you don't want that, you can use the category mode (see this example and this fiddle with your data).
xaxis: {
//ticks: 12,
tickColor: '#ffffff',
mode: 'categories'
}
PS: 12 ticks are not possibly with your data, as there are only 4 datapoints defined.
That flot reads all data as numbers by default is described here in the documentation.
Flotr examples use a for loop to create random data, so the first index will always be sequential.
[[51,1700],[52, 1750],[1,1600],[2,1675]];
Your arrays show that flotr must be doing a sort on the array before painting the data sets as lines, bar-graphs or whatever.
I can only suggest you create a timestamp from the months and there's a time setting you can in flotr settings to format the dates as you want.
The other way is replace your anomalous data (months) with sequential indices:
var arr = [[51,1700],[52, 1750],[1,1600],[2,1675]];
for(var i=0; i<arr.length; i++) arr[1][0] = i;
Flot is doing exactly what it should do for a line chart (or any type of x-y graph). It's showing the last two points of your dataset on the left because 1 and 2 are indeed less than 51 and 52. I'm guessing that you're trying to show data that crosses a year boundary. You need to make the first two weeks of the second year later than the last two of the first. You could use actual dates instead of week numbers, in which case Flot would handle it fine. That would also give you more flexibility in labeling the x-axis. But as a quick fix, just add 52 to the second year's data, e.g.:
var scheduled = [[51,1700],[52, 1750],[53,1600],[54,1675]];
var actual = [[51,1320],[52, 1550],[53,1575],[54,1600]];

HighCharts - Add vertical lines from a desire point

Need to draw vertical lines from a desired point rather than starting from 0.
plotLines: [{
color: '#FF0000',
width: 1,
value: 4
}, {
color: '#FF0000',
width: 1,
value: 7
}],
Here is the fiddler link: http://jsfiddle.net/bpswt3tr/4/
My requirement is to draw first vertical line from when y value is 110.2 and 2nd line from when y value is 135.6 instead of starting from zero. i.e above the plot line only. Please suggest how can I achieve this? Thanks.
Considering the documentation it is unlikely that HighCharts supports this by default, as you are only allowed to associate a value of the current axis with the line.
You might need a preprocessing step that inverts you function to get the appropriate X values. Something like:
invert(data, Y) -> list of X values with data[X] = Y
You can do this on the chart.events.load call. If you know these are the points you want to add marker elements to then it is fairly straightforward. You first get the current max label value for the yAxis. Then you add a series to the chart with the starting point being your series' value and the second point being the max viewable yAxis value. Then do the same for the second point you want to add a bar to. Then, you need to re-set the yAxis max value to the initial state because highcharts will try to increase the scale to accommodate the new points.
chart: {
events: {
load: function () {
var yMAx = this.yAxis[0].max;
console.log(yMAx);
this.addSeries({
data: [{
x: 4,
y: 110.2,
marker: {
symbol: 'triangle'
}
}, {
x: 4,
y: yMAx,
marker: {
symbol: 'triangle-down'
}
}, ],
showInLegend: false,
color: 'red',
marker: {
enabled: true
}
});
this.addSeries({
data: [{
x: 7,
y: 135.6,
marker: {
symbol: 'triangle'
}
}, {
x: 7,
y: yMAx,
marker: {
symbol: 'triangle-down'
}
}, ],
showInLegend: false,
color: 'red',
marker: {
enabled: true
}
});
this.yAxis[0].update({
max: yMAx
});
}
}
}
Sample demo.

Making two series point in opposite directions in highcharts

I have a column chart with two series, one of which I want to go down and the other up, like this:
However both of the series have positive y-values, which I can't change, e.g.
blue = [1746181, 1884428, 2089758, 2222362, 2537431, 2507081, 2443179,
2664537, 3556505, 3680231, 3143062, 2721122, 2229181, 2227768,
2176300, 1329968, 836804, 354784, 90569, 28367, 3878];
grey = [1656154, 1787564, 1981671, 2108575, 2403438, 2366003, 2301402, 2519874,
3360596, 3493473, 3050775, 2759560, 2304444, 2426504, 2568938, 1785638,
1447162, 1005011, 330870, 130632, 21208];
Using highcharts options, is it possible to have a chart like this? The example I used for the screenshot is this jsFiddle if it's useful to anyone, however it has a series with negative values which is not an option for me. Instead my data is more like this fiddle
I would try to use two separate yAxes: http://jsfiddle.net/zares7x9/2/, where one of them is reversed:
yAxis: [{
title: {
text: null
},
top: '5%',
height: '45%',
labels: {
formatter: function () {
return (Math.abs(this.value) / 1000000) + 'M';
}
},
min: 0,
max: 4000000
}, {
title: {
text: null
},
labels: {
formatter: function () {
return (Math.abs(this.value) / 1000000) + 'M';
}
},
offset: 0,
showFirstLabel: false, // hide 0-value
reversed: true, //reverse
top: '50%',
height: '45%',
min: 0,
max: 4000000
}],
Setting top and height allows you to render axes like one. Note, that you need to set for one of the series yAxis: 1, to inform Highcharts which series belongs to which axis.

How to draw a line at yaxis = 0 with jQPlot?

I am using jQPlot and disabled the grid lines on my charts (drawGridlines: false). However, I would like to have a line at yaxis = 0, and I also would like to make sure that the 0 appears as well. Is this doable easily?
Thanks!
You can add an object in canvasOverlay :
var options={ //jqplot options
canvasOverlay: {
show: true,
objects: [
{
horizontalLine: {
name: "y=0",
y: 0,
yaxis: "yaxis",
lineWidth: 1,
color: "rgb(0,0,0)",
shadow: false
}
}
]
}
}
Don't forget to include jqplot.canvasOverlay.min.js plugin.

Categories