How to show first and last label of x axis Highcharts - javascript

I tried some solution on other answers but I couldn't get the result what I want.. please help me.
I want to show first x axis label and last one in highcharts.
I tried {endOnTick: true, showLastLabel: true} from this answer(Force Highcharts to show last x-axis label) but it shows just some number on the last.. not the actual last label.
This is my x axis option
xAxis: {
type: 'Month',
// tickInterval is 5 this time
tickInterval: <?php echo number_format($num_results/5, 0);?>,
endOnTick: true, // it shows "25" at the end of the label. not "2019-06"
showLastLabel: true, // Default is true though..
labels: {
autoRotation: 0
},
//I get those categories from server
//so it could be different every time
//but this time I just write the result of it.
categories: ["2017-07","2017-08","2017-09","2017-10","2017-11","2017-12","2018-01","2018-02","2018-03","2018-04","2018-05","2018-06","2018-07","2018-08","2018-09","2018-10","2018-11","2018-12","2019-01","2019-02","2019-03","2019-04","2019-05","2019-06"]
}
expected x axis labels are
"2017-07 2017-12 2018-05 2018-10 2019-03 2019-06"
the actual result is
"2017-07 2017-12 2018-05 2018-10 2019-03 25"

Ahh I used tickPositioner and solved it!
xAxis: {
type: 'Linear',
tickmarkPlacement: 'on',
tickPositioner: function() {
var positions = [],
ext = this.getExtremes(),
xMax = Math.round(ext.max),
xMin = Math.round(ext.min);
for (var i = xMin; i < xMax; i++) {
if (i % <?php echo number_format($num_results/3,0);?> == 0) {
positions.push(i);
}
}
positions.push(xMax);
return positions;
},
labels: {
autoRotation: 0,
},
categories: ["2017-07","2017-08","2017-09","2017-10","2017-11","2017-12","2018-01","2018-02","2018-03","2018-04","2018-05","2018-06","2018-07","2018-08","2018-09","2018-10","2018-11","2018-12","2019-01","2019-02","2019-03","2019-04","2019-05","2019-06"]
}

You are missing 2 categories to show 2019-06
...
categories: ["2017-07","2017-08","2017-09","2017-10","2017-11",
"2017-12","2018-01","2018-02","2018-03","2018-04",
"2018-05","2018-06","2018-07","2018-08","2018-09",
"2018-10","2018-11","2018-12","2019-01","2019-02",
"2019-03","2019-04","2019-05","2019-06","24th","the 25th"]
},
Fiddle

Related

Charts.js line chart: Show the most recent date on x-axis when setting ticks.maxTicksLimit

I'm currently using making a line chart with Charts.js over the past 30 years.
Although I have a data point for every year, I can't put a label for each year on the x-axis. 30 years won't fit there. So, I've chosen to only list some years, by setting
ticks: {
maxTicksLimit: SOME_LIMIT_I_MADE
}
Here is a photo of what my chart looks like
The most recent data point is in 2020 and the oldest is in 1991.
It seems that setting maxTicksLimit starts the scale at the earliest year. Then the scale skips forwards in regular intervals.
What I really want is for the most recent year 2020 to be displayed on the scale (so that users can see that the data is new). Is there a way to make the scale start at the max year, and then the skip backwards from there (the opposite of how my graph currently is)?
Thanks!
This could be solved by somehow implement your own ticks.maxTicksLimit on the xAxis. You would have to proceed as follows.
Define the xAxis as a time cartesian axis that accepts the data as an array of data points using an object containing x and y properties.
Generate a labels array out of the years contained in your data. This array should contain the starting year and end year together with a number of equally spread years between both (see function createLabels in the code snippet below).
Tell Chart.js to generate ticks on the xAxis from given labels by defining tick.sources: 'labels'.
const data = [];
for (let year = new Date().getFullYear() - 29; year <= new Date().getFullYear(); year++) {
data.push({
x: year.toString(),
y: Math.floor((Math.random() * 6) + 1)
})
}
const maxTicksLimit = 6;
function createLabels() {
const years = data.map(o => Number(o.x));
const startTime = years[0];
const endTime = years[years.length - 1];
const tickGap = (endTime - startTime) / (maxTicksLimit - 1);
const labels = [startTime];
for (let i = 1; i < maxTicksLimit - 1; i++) {
labels.push(Math.round(startTime + i * tickGap));
}
labels.push(endTime);
return labels.map(l => l.toString());
}
new Chart('myChart', {
type: 'line',
data: {
labels: createLabels(),
datasets: [{
label: 'Demo',
fill: false,
data: data,
borderColor: 'blue'
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
parser: 'YYYY',
unit: 'year'
},
ticks: {
source: 'labels'
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="80"></canvas>

Highcharts: Can sunburst chart show percentage share to depict part-to-whole relationship like pie charts?

Percentage share is used to depict the part-to-whole relationship in a chart.
Observe the point.percentage property used in Pie chart series data labels to show the percentage share with respect to the whole chart :
http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/demo/pie-basic/
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
}
I would like to achieve the following:
Reference of this example : https://www.grapecity.com/en/blogs/sunburst-chart-roadmap-what-would-you-like-to-see
I know that the above percentage share with respect to parent and with respect to whole chart, can be achieved by manually setting the respective values. But that involves manual calculations.
I want to know if Highcharts supports point.percentage for Sunburst charts. Its not given in the API reference and I also did not get it on debugging an example in JS Fiddle.Is there any other way to achieve it?
No, point.percentage is only for stacked series or pies: https://api.highcharts.com/class-reference/Highcharts.Point#.percentage
However, if you use a dataLabels.formatter, it's easy to calculate the percentage for each slice. In the formatter function, you'll have access to the current slice (point) and all the rest of the chart data:
Example (change series.custom.percentage to select percentage calculation)
series: [{
type: 'sunburst',
data: ...,
//https://api.highcharts.com/highcharts/series.sunburst.custom
custom: {
percentage: 'whole', //'whole' or 'parent'
},
dataLabels: {
formatter: function() {
const point = this.point,
series = this.series,
mode = series.options.custom && series.options.custom.percentage;
const chartTotal = series.__myTotal || (series.__myTotal = series.data.map(p => p.options.value || 0).reduce((a, b) => a + b));
let percentage;
switch(mode) {
case 'whole':
percentage = point.value/chartTotal;
break;
case 'parent':
const group = point.parent && series.chart.get(point.parent),
total = group ? group.value : chartTotal;
percentage = point.value/total;
break;
}
const val = (percentage === undefined) ? point.value : (percentage * 100).toFixed(1) + '%';
return point.name + '<br>' + val;
},
},
...
https://jsfiddle.net/pntjgqby/

Highcharts: display peak values

I would like to display difference between 2 points on my Highcharts graph. Only when it's a major "peak" difference.
Here's a "static" example :
$(function () {
$('#container').highcharts({
chart: {
type: 'areaspline'
},
series: [{
data: [560,500,476,453,356,{
y: 590,
dataLabels: {
enabled: true,
formatter: function () {return '+243';}
}
},497,478,465,465,465,410,398]
}]
});
});
http://jsfiddle.net/vr1a61wy/
How can I compare all point values with the previous ?
For example, something like that (not "real code)
if(prevValue > 200) {
displayDataLabel();
}
function displayDataLabel() {
peak = this.datalabel - prev.datalabel;
return peak;
}
The goal is to have a clean json file only with values and peaks calculated by javascript.
Is it possible ?
You can use the plotOptions.series.dataLabels.formatter to do this comparison. To do the comparison you will utilize this.x, this.y and this.series to look up the previous point.
An example formatter function would be (JSFiddle):
formatter: function() {
if(this.x > 0 && this.y - this.series.data[this.x-1].y >= PEAKDIFF) {
return "+" + (this.y - this.series.data[this.x-1].y);
}
return null;
}
Where PEAKDIFF is the value you want the difference to be before showing the label. If you want large negative drops to show as well you'd do the same with Math.abs.

Major and minor ticks in FLOT

Some charting/plotting libraries, e.g. matplotlib for Python, has the concept of major and minor ticks (with corresponding major and minor gridlines). I have been looking around, and I think this doesn't exist in FLOT. It seems that there is only one category of tick.
Isn't it possible to make something like below, and if yes, then how?
E.g., as in the illustration below, major ticks for every 1.0, and minor ticks for every 0.2.
You are correct that flot does not support this natively.
To replicate your drawing, I would use grid markings and add a thicker line at each whole number tick:
$.plot("#placeholder", [ d1 ], {
xaxis: {
tickSize: 0.2 // regular tick at 0.2
},
grid: {
markings: function (axes) {
var markings = [];
var xTicks = axes.xaxis.ticks;
for (var i = 0; i < xTicks.length; i++){ // loop all the ticks and add a black line at each whole number
if (xTicks[i].v % 1 === 0){
markings.push({ xaxis: { from: xTicks[i].v - 0.005, to: xTicks[i].v + 0.005 }, color: 'black' });
}
}
return markings;
}
}
});
Produces (example here):
If anyone wants to add your own unlabelled minor ticks at the minortick divisions you want you can do this. (Default minor ticks is 5 and can't easily be overidden)
My data is time based showing two years with markers every three months.
xaxis: {
mode: "time",
timeformat: "%b %Y",
minTickSize: [3, "month"],
showMinorTicks:false,
},
grid: {
markings: function (axes) {
var markings = [];
var month_time= 2629700; // year in seconds divided by 12
var offset=0;
var linespread=36000; // set line thickness
var xTicks = axes.xaxis.ticks;
for (var i = 0; i < xTicks.length; i++){
// loop all the ticks and add a dark line at each main group
markings.push({ xaxis: { from: xTicks[i].v - linespread, to: xTicks[i].v + linespread }, color: '#aaa' });
for (var k = 1; k < 3; k++){
//use subdvision to add minor ticks
offset=month_time*k;
markings.push({ xaxis: { from: xTicks[i].v + offset - linespread, to: xTicks[i].v + offset + linespread }, color: '#ddf' });
}
}
return markings;
}
}

Adding color to the max value in a dynamically generated chart?

The jsfiddle link is here http://jsfiddle.net/MzQE8/110/
The problem here I feel is in my JavaScript.
I input values to the series object in a HighChart from an array. On the array I am trying to find index and the value of the maximum element and then I am saving the maximum array element back with this modification
yArr[index] = {
y: value,
color: '#aaff99'
};
So that It appears as a diferent color from the rest of the points on the graph which is a dynamic one. That is its sliding one.
Here is my code
$(function () {
$(document).ready(function () {
Highcharts.setOptions({
global: {
useUTC: false
}
});
var chart;
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0];
//As this graph is generated due to random values. I am creating an Array with random values.
var yArr = [];
yArr[0] = Math.random();
yArr[1] = Math.random();
yArr[2] = Math.random();
yArr[3] = Math.random();
setInterval(function () {
console.log(yArr.length);
var x = (new Date()).getTime(), // current time
y = Math.random();
var index = findIndexOfGreatest(yArr);
var value = yArr[index];
yArr[index] = {
y: value,
color: '#aaff99'
};
series.addPoint([x, yArr.shift()], true, true);
yArr.push(Math.random());
}, 1000);
}
}
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'datetime',
tickPixelInterval: 450
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
plotOptions: {
series: {
lineWidth: 1
}
},
tooltip: {
formatter: function () {
return '<b>' + this.series.name + '</b><br/>' + Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' + Highcharts.numberFormat(this.y, 2);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Random Data',
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i++) {
data.push({
x: time + i * 1000,
y: yArr.shift()
});
}
return data;
})(),
color: 'red'
}]
});
});
function findIndexOfGreatest(array) {
var greatest;
var indexOfGreatest;
for (var i = 0; i < array.length; i++) {
if (!greatest || array[i] > greatest) {
greatest = array[i];
indexOfGreatest = i;
}
}
return indexOfGreatest;
}
});
I feel my idea is correct but there are big holes in my implementation. I guess.
Thanks
See demo: http://jsfiddle.net/MzQE8/350/
All y-values are stored in series.yData, so you don't have to create another array for that. Now just update point which is the highest one, and add new points. Something like above demo, code:
events: {
load: function () {
// set up the updating of the chart each second
var series = this.series[0],
index = series.yData.indexOf(series.yData.max());
// mark first max points
this.series[0].prevMax = this.series[0].data[index];
this.series[0].prevMax.update({
color: '#aaff99'
});
setInterval(function () {
var x = (new Date()).getTime(), // current time
y = Math.random(),
color = null,
index, max;
if (series.prevMax && series.prevMax.update) {
// remove previously colored point
if (y > series.prevMax.y) {
series.prevMax.update({
color: null
}, false);
color = '#aaff99';
// store max, which is last point
series.prevMax = series.data[series.yData.length];
}
} else {
max = series.yData.max();
index = series.yData.indexOf(max);
if(y > max) {
color = '#aaff99';
series.prevMax = series.data[series.yData.length];
} else {
series.prevMax = series.data[index];
series.prevMax.update({
color: '#aaff99'
}, false)
}
}
// add new point
series.addPoint({
x: x,
y: y,
color: color
}, true, true);
}, 1000);
}
}
im not to sure what your seeking but if i understand correctly you want the bullet marks to be a different color to differentiate from the others. i wont include source code because what you have included in your js fiddle is pretty advanced stuff and you will be able to figure this out no problem.
calculate (all total values added together / 256 + i) * 255 (or something similar)
the i represents the bullet increment in a loop. please for give the algorithm i haven't slept in 32 hours and i know its def. suggested you check it.
Oh.. kay here is the updated solution working out on paper
http://i966.photobucket.com/albums/ae147/Richard_Grant/Untitled-1_zps7766a939.png
I PUT A LOT OF WORK INTO THIS! so please!!! use it well -.-'
What is happening here is i drew out a graph with values going from 0 - 200 and i labeled the graph results 1 - 4, i also made this the x coordinates cause im lazy.
In the workflow RES = means results or X, Val = Value or Y
These are used to calculate RGB values and i solved the first 3 results. the first result tangent should always be 0 because any number divisible by 0 is 0, and any number multiplied by 0 is 0.
When i say tangent i mean the angle of the point by the 200, 0 value (invisible point). in this formula the angle would not be perfected because the x and y on the graph are not equal, one is 200 max and the other is 4 max. if i wanted this to be accurate i would have turned the tangent into a percent and multiplied it by 255. but i didn't.
I feel i have given you the necessary tools to complete your request on your own now :) if you do not understand how i did this or found this algorithm, just fall back to random colors.
Thanks John doe, your question helped me. This is the function i used to change the color of the maximum value of my y axis:
function () {
var maximum = chart.yAxis[0].dataMax;
var index = series.yData.indexOf(maximum);
chart.series[0].data[index].update({ color: '#aaff99' });
}
It may help other people too.

Categories