Are you able to offset a secondary y-axis in ChartJS, by a decimal value, whilst keeping the same scale for both y-axes? - javascript

I am currently working with two datasets, both in meters, but the left hand axis displays a dataset with an offset of 11.74m along the y-axis. The right hand axis ignores this offset, hence y1 == y2 when y1 = 11.74 and y2 = 0.
This being the case, is there a way to keep integer tick values on both axes despite the decimal offset between the two? Not sure if I've got the Y2 offset correct in the graph below, but I think this is roughly what I'm trying to achieve - basically fixed gridline/tick intervals of Y1 for both axes, except for Y2:
The live code I'm working on is a bit too unwieldly for Stack Overflow, but the code below roughly achieves what I'm after - would be nice if there was a way to cleanly declare an offset of -0.26 without then also having to explicitly declare the rest of the ticks:
var ticks = [5, 4, 3, 2, 1, -0.26];
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
datasets: [{
data: [0, 0.1, 0.5, 5, 3.5, 3, 3.25, 2, 1.5, 1]
}]
},
options: {
scales: {
yAxes: [{
ticks: {
autoSkip: false,
min: ticks[ticks.length - 1],
max: ticks[0]
},
afterBuildTicks: function(scale) {
scale.ticks = ticks;
return;
},
beforeUpdate: function(oScale) {
return;
}
}]
}
}
});
https://jsfiddle.net/wxp1fLk0/5/

Solution below after much fiddling. offset in the getTickArray() function specifies the left-hand axis value that coincides with 0 on the right hand axis. I think the afterBuildTicks and beforeUpdate keys then allow you to position ticks with more precision (I think).
https://jsfiddle.net/zjxukf57/47/
function getRandomDataset(lowerBound, upperBound, count) {
let output = [];
for (let index = 0; index < count; index++) {
let newPoint = Math.floor((Math.random() * upperBound) + lowerBound);
output.push(newPoint);
}
return output;
}
function arrayMin(arr) {
var len = arr.length, min = Infinity;
while (len--) {
if (arr[len] < min) {
min = arr[len];
}
}
return min;
}
function arrayMax(arr) {
var len = arr.length, max = -Infinity;
while (len--) {
if (arr[len] > max) {
max = arr[len];
}
}
return max;
}
function getTickArray(offset, increment, leftData, rightData) {
let ticksLeft = [];
let ticksRight = [];
let leftMin = arrayMin(leftData);
let leftMax = arrayMax(leftData);
let rightMin = arrayMin(rightData);
let rightMax = arrayMax(rightData);
let tick = leftMin;
let tickRight = tick - offset;
let wholeTick = Math.ceil(tick); // ? Gets first left-hand integer above minimum tick value
let wholeTickRight = Math.ceil(tickRight); // ? Gets first right-hand integer above minimum tick value
let maxValue = leftMax > rightMax + offset ? leftMax : rightMax + offset;
// ? Push minimum decimal ticks
ticksLeft.push(tick);
ticksRight.push(tickRight);
while (wholeTick < maxValue) {
ticksLeft.push(wholeTick);
ticksRight.push(wholeTickRight);
wholeTick = wholeTick + 1*increment;
wholeTickRight = wholeTickRight + 1*increment;
}
// ? Push minimum decimal ticks
ticksLeft.push(maxValue);
ticksRight.push(maxValue - offset);
return [ ticksLeft, ticksRight ];
}
let datasetOne = getRandomDataset(8, 15, 10); // ? Ten random numbers between 8 and 15
let datasetTwo = getRandomDataset(0, 7, 10); // ? Ten random numbers between 0 and 7
var ticks = getTickArray(11.76, 2, datasetOne, datasetTwo);
console.log(ticks)
var ticks1 = ticks[0];
var ticks2 = ticks[1];
console.log(datasetOne);
console.log(datasetTwo);
// ? Chart Config
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
datasets: [{
data: datasetOne,
yAxisID: 'A',
label: "left",
borderColor: "#FF0000",
backgroundColor: 'rgba(0, 0, 0, 0)'
},
{
data: datasetTwo,
yAxisID: 'B',
label: "right",
borderColor: "#348632",
backgroundColor: 'rgba(0, 0, 0, 0)'
}]
},
options: {
scales: {
yAxes: [{
id: 'A',
ticks: {
autoSkip: false,
min: ticks1[ticks1.length - 1],
max: ticks1[0]
},
afterBuildTicks: function(scale) {
scale.ticks = ticks1;
return;
},
beforeUpdate: function(oScale) {
return;
},
gridLines: {
color: "#FF0000"
}
},
{
id: 'B',
ticks: {
autoSkip: false,
min: ticks2[ticks2.length - 1],
max: ticks2[0],
callback: function(value, index, values) {
return value;
}
},
afterBuildTicks: function(scale) {
scale.ticks = ticks2;
return;
},
beforeUpdate: function(oScale) {
return;
},
position: "right",
gridLines: {
color: "#348632"
}
}]
}
}
});

Related

animation of a graph of an equation javascript

I'm stuck on this issue and don't know where to put my hands.
I have to draw in javascript the animation of the graph of the equation y = x ^ 3
what do i mean?
knowing y (for example y = 10) I would like the graph to start from (0; 0) up to (x; 10) following the equation y = x ^ 3
also I would like to create a button which can be clicked during the animation and tells me what y is the graph at that precise moment
for now thanks to chart.js i managed to do this:
JS
var ctx = document.getElementById("myChart");
var data = {
labels: [1, 2, 3, 4, 5],
datasets: [
{
function: function(x) { return x*x*x },
borderColor: "rgba(153, 102, 255, 1)",
data: [],
fill: true
}]
};
Chart.pluginService.register({
beforeInit: function(chart) {
var data = chart.config.data;
for (var i = 0; i < data.datasets.length; i++) {
for (var j = 0; j < data.labels.length; j++) {
var fct = data.datasets[i].function,
x = data.labels[j],
y = fct(x);
data.datasets[i].data.push(y);
}
}
}
});
var myBarChart = new Chart(ctx, {
type: 'line',
data: data,
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
}
}]
}
}
});
HTML
<canvas id="myChart"></canvas>
result
for now I only have the graph, there is no animation and I cannot select the maximum y
how can I do?
To set max amount on your y Axes you can use the max property or suggestedMax if you want to make sure that if the data goes bigger the axis adapts. For the animation you can write custom logic as in the example underneath. I only dont know how to get the value its at on the click:
const labels = [1, 2, 3, 4, 5]
const totalDuration = 5000;
const delayBetweenPoints = totalDuration / labels.length;
const previousY = (ctx) => ctx.index === 0 ? ctx.chart.scales.y.getPixelForValue(100) : ctx.chart.getDatasetMeta(ctx.datasetIndex).data[ctx.index - 1].getProps(['y'], true).y;
var options = {
type: 'line',
data: {
labels,
datasets: [{
label: '# of Votes',
data: [],
borderWidth: 1,
function: function(x) {
return x * x * x
},
borderColor: 'red',
backgroundColor: 'red'
}]
},
options: {
scales: {
y: {
max: 250
}
},
animation: {
x: {
type: 'number',
easing: 'linear',
duration: delayBetweenPoints,
from: NaN, // the point is initially skipped
delay(ctx) {
if (ctx.type !== 'data' || ctx.xStarted) {
return 0;
}
ctx.xStarted = true;
return ctx.index * delayBetweenPoints;
}
},
y: {
type: 'number',
easing: 'linear',
duration: delayBetweenPoints,
from: previousY,
delay(ctx) {
if (ctx.type !== 'data' || ctx.yStarted) {
return 0;
}
ctx.yStarted = true;
return ctx.index * delayBetweenPoints;
}
}
}
},
plugins: [{
id: 'data',
beforeInit: function(chart) {
var data = chart.config.data;
for (var i = 0; i < data.datasets.length; i++) {
for (var j = 0; j < data.labels.length; j++) {
var fct = data.datasets[i].function,
x = data.labels[j],
y = fct(x);
data.datasets[i].data.push(y);
}
}
}
}]
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
var chart = new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.0.1/chart.js" integrity="sha512-HJ+fjW1Hyzl79N1FHXTVgXGost+3N5d1i3rr6URACJItm5CjhEVy2UWlNNmFPHgX94k1RMrGACdmGgVi0vptrw==" crossorigin="anonymous"></script>
</body>

graph of an equation animated javascript (crash game)

i don't know how to get out of this problem
I have the animation of the graph of the equation y = x ^ 2
this:
const labels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
const totalDuration = 2000;
const delayBetweenPoints = totalDuration / labels.length;
const previousY = (ctx) => ctx.index === 0 ? ctx.chart.scales.y.getPixelForValue(100) : ctx.chart.getDatasetMeta(ctx.datasetIndex).data[ctx.index - 1].getProps(['y'], true).y;
var options = {
type: 'line',
data: {
labels,
datasets: [{
label: '# of Votes',
data: [],
borderWidth: 1,
function: function(x) {
return x * x
},
borderColor: "rgba(153, 102, 255, 1)",
fill: true
}]
},
options: {
scales: {
y: {
max: 200
},
x: {
suggestedMax: 210
}
},
animation: {
x: {
type: 'number',
easing: 'linear',
duration: delayBetweenPoints,
from: NaN, // the point is initially skipped
delay(ctx) {
if (ctx.type !== 'data' || ctx.xStarted) {
return 0;
}
ctx.xStarted = true;
return ctx.index * delayBetweenPoints;
}
},
y: {
type: 'number',
easing: 'linear',
duration: delayBetweenPoints,
from: previousY,
delay(ctx) {
if (ctx.type !== 'data' || ctx.yStarted) {
return 0;
}
ctx.yStarted = true;
return ctx.index * delayBetweenPoints;
}
}
}
},
plugins: [{
id: 'data',
beforeInit: function(chart) {
var data = chart.config.data;
for (var i = 0; i < data.datasets.length; i++) {
for (var j = 0; j < data.labels.length; j++) {
var fct = data.datasets[i].function,
x = data.labels[j],
y = fct(x);
data.datasets[i].data.push(y);
}
}
}
}]
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
var chart = new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.0.1/chart.js" integrity="sha512-HJ+fjW1Hyzl79N1FHXTVgXGost+3N5d1i3rr6URACJItm5CjhEVy2UWlNNmFPHgX94k1RMrGACdmGgVi0vptrw==" crossorigin="anonymous"></script>
</body>
I have to add 3 things and I don't know how to get out of it
how can I define a Y value for which the line stops going up?
if this Y is bigger than the axis data, how can they adapt?
how can I create a button which when clicked tells me the exact Y value at that moment during the animation?
I wish something like this graph would come out:
https://www.youtube.com/watch?v=w48ahDZQPnQ
You can try setting the Y max value like this in your code to auto adjust Y axis scale.
beforeInit: function(chart) {
var data = chart.config.data;
let maxValue = 0;
for (var i = 0; i < data.datasets.length; i++) {
for (var j = 0; j < data.labels.length; j++) {
var fct = data.datasets[i].function,
x = data.labels[j],
y = fct(x);
if (maxValue < y) {
maxValue = y;
}
data.datasets[i].data.push(y);
}
}
chart.options.scales.y.max = maxValue;
}

Plotline (vertical line) in highcharts scatter chart

https://jsfiddle.net/7zL0v5oq/
I would like to have a plotline at today's date. The list can get quite long and in that case it helps with having an oversight. I fear it doesn't work because it is a scatter chart but I don't know what the problem is. I've searched all over the place but everything leads to plotlines, which clearly doesn't work. I would also be thankful if anyone knew, whether there was an easy way to filter my data the way I have it (standard highcharts filtering is deactivated but doesn't really help because of the static y values, so I get a huge, white space in the middle unless I filter at the edges. Thank you in advance for your help.
data = [{
"id": 1,
"release": "Software1",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2014-04-01",
"sale_ended_on": "2013-04-01",
"security_vul_support_ended_on": "2015-04-01",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2018-03-31",
"updated_dates_on": "2012-10-03",
"created_at": "2018-05-04T18:53:21.301+02:00",
"updated_at": "2018-05-16T08:36:24.940+02:00"
},
{
"id": 2,
"release": "Software2",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2019-07-24",
"sale_ended_on": "2017-07-31",
"security_vul_support_ended_on": "2020-07-24",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2022-07-31",
"updated_dates_on": "2015-08-14",
"created_at": "2018-05-05T04:00:44.170+02:00",
"updated_at": "2018-05-16T08:36:29.325+02:00"
},
{
"id": 3,
"release": "Software3",
"routine_failure_analysis_ended_on": null,
"sw_maintenance_releases_ended_on": "2018-03-01",
"sale_ended_on": "2017-03-01",
"security_vul_support_ended_on": "2018-12-01",
"service_contract_renewal_ended_on": null,
"svc_attach_ended_on": null,
"support_ended_on": "2022-02-28",
"updated_dates_on": "2016-09-02",
"created_at": "2018-05-05T04:00:44.401+02:00",
"updated_at": "2018-05-16T08:36:31.643+02:00"
}
];
const colors = ["#516", "#1781e3", "#25b252", "#20c997", "#ffc107", "#ff8b2e", "#dd1122"];
//Change to store y value paired to release/pid
var change = {};
//Which y values need to be displayed
var ticks = [0];
//Description of events
var sale = "Sale";
var support = "Support";
var svc = " SVC attach";
var sw = "Software maintenance";
var routine = "Routine failure analysis";
var service = "Service contract renewal";
var security = "Security vulnerability support";
//Data array for series
var high = [];
data.sort(function(a, b) {
return Date.parse(a.support_ended_on) < Date.parse(b.support_ended_on) ? 1 : -1
})
for (var i = 0; i < data.length; i++) {
var arr = [{
x: Date.parse(data[i].sale_ended_on),
y: (i + 1) * 20,
color: colors[0],
myValue: sale
},
{
x: Date.parse(data[i].sw_maintenance_releases_ended_on),
y: (i + 1) * 20,
color: colors[1],
myValue: sw
},
{
x: Date.parse(data[i].security_vul_support_ended_on),
y: (i + 1) * 20,
color: colors[2],
myValue: security
},
{
x: Date.parse(data[i].svc_attach_ended_on),
y: (i + 1) * 20,
color: colors[3],
myValue: svc
},
{
x: Date.parse(data[i].routine_failure_analysis_ended_on),
y: (i + 1) * 20,
color: colors[4],
myValue: routine
},
{
x: Date.parse(data[i].service_contract_renewal_ended_on),
y: (i + 1) * 20,
color: colors[5],
myValue: service
},
{
x: Date.parse(data[i].support_ended_on),
y: (i + 1) * 20,
color: colors[6],
myValue: support
}
];
var key, value;
line = [{
x: Date.parse(data[i].sale_ended_on),
y: (i + 1) * 20
}, {
x: Date.parse(data[i].support_ended_on),
y: (i + 1) * 20
}]
//Adding to change list, so we can add release/pid as label to y axis
key = (i + 1) * 20;
ticks.push(key);
if (data[i].pid) {
value = data[i].pid;
} else {
value = data[i].release;
}
change[key] = value;
//Expanding high (which is used for the highcharts series) with arr (all points for one pid)
if (data[i].pid) {
high.push({
label: data[i].pid,
name: data[i].pid,
type: 'scatter',
data: arr
}, {
type: 'line',
data: line,
linkedTo: ":previous"
});
} else {
high.push({
label: data[i].release,
name: data[i].release,
type: 'scatter',
data: arr,
showInLegend: false
}, {
type: 'line',
data: line,
linkedTo: ":previous"
});
}
}
Highcharts.chart("container", {
chart: {
height: data.length * 75
},
credits: {
enabled: false
},
yAxis: {
title: {
text: null
},
tickPositions: ticks,
visible: true,
labels: {
formatter: function() {
var value = change[this.value];
return value !== 'undefined' ? value : this.value;
}
}
},
xAxis: {
plotlines: [{
color: "#dd1122",
width: 2,
value: +new Date()
}],
type: 'datetime',
},
plotOptions: {
scatter: {
marker: {
symbol: 'circle',
radius: 7,
lineWidth: 2
}
},
line: {
enableMouseTracking: false,
marker: {
enabled: false
},
color: '#bbb',
lineWidth: 3
}
},
tooltip: {
formatter: function() {
var str = '<b>' + this.series.name + '</b><br/>'
if (this.point.myValue) {
str += this.point.myValue;
} else {
str += "Corrupted data!";
}
if (this.point.x < Date.parse(new Date))
return str += " ended on:<br/>" + Highcharts.dateFormat('%e %b %Y', new Date(this.x));
else
return str += " will end on:<br/>" + Highcharts.dateFormat('%e %b %Y', new Date(this.x));
},
shared: false
},
series: high
})
You have a typo, use plotLines instead of plotlines:
xAxis: {
plotLines: [{
...
}],
...
}
Live demo: https://jsfiddle.net/BlackLabel/p3u8ejtb/
API Reference: https://api.highcharts.com/highcharts/xAxis.plotLines

Chart.js: Combined Line and Bar Data

I want to create a Chart with Chart.js containing two different datasets: One Line Data Set and one Bar Data Set.
You can see my whole code for that here:
/**
*
*/
function initCombinedChart() {
/**
*
*/
$("canvas").each(function() {
var config = getConfigCombined($(this).attr("id"));
var context = $(this);
var combined = new Chart(context, config);
});
}
/**
*
* #param id
* #returns {___anonymous464_473}
*/
function getConfigCombined(id) {
var currentId = id;
var currentIdNumber = currentId.substring((currentId.lastIndexOf("_") + 1), currentId.length);
var entry = $("#" + id).data("entry");
var labelMeasure = $("#evaluations_combined_measures").data("txt");
var labelInsulin = $("#evaluations_combined_insulins").data("txt");
var datasetLine = dataCombinedLine(labelMeasure, entry);
var datasetCombined = dataCombinedBar(labelInsulin, entry);
var config = {
type: "bar",
data: {
labels: labelsFromEntry(entry),
datasets: []
},
options: {
responsive: true,
title: {
display: false
},
legend: {
position: "bottom"
},
scales: {
xAxes: [{
position: "bottom",
type: "time",
time: {
unit: "hour",
format: "HH:mm",
tooltipFormat: "HH:mm",
displayFormats: {
hour: "HH:mm",
day: "HH:mm",
week: "HH:mm",
month: "HH:mm",
quarter: "HH:mm",
year: "HH:mm"
}
},
gridLines : {
display : false
}
}],
yAxes: [{
type: "linear",
display: true,
position: "left",
id: "y-axis-0",
gridLines: {
show: true,
}
}, {
type: "linear",
display: true,
position: "right",
id: "y-axis-1",
gridLines: {
show: false
}
}]
},
}
}
if (datasetLine != null) {
config.data.datasets.push(datasetLine);
}
if (datasetCombined != null) {
config.data.datasets.push(datasetCombined);
}
return config;
}
/**
*
* #param entry
* #returns {Array}
*/
function labelsFromEntry(entry) {
var result = [];
var entryCombined;
var entryMeasure;
var entryInsulin;
if (entry.indexOf("-") >= 0) {
entryCombined = entry.split("-");
entryMeasure = entryCombined[0];
entryInsulin = entryCombined[1];
} else {
entryMeasure = entry;
entryInsulin = "";
}
var entryMeasureArray = entryMeasure.split(";");
var entryInsulinArray = entryInsulin.split(";");
entryMeasureArray.forEach(function(entry) {
var entryPair = entry.split(",");
var date = parseFloat(entryPair[0]);
var dateFormat = moment(date).format("HH:mm");
if (!result.includes(dateFormat)) {
result.push(dateFormat);
}
});
entryInsulinArray.forEach(function(entry) {
var entryPair = entry.split(",");
var date = parseFloat(entryPair[0]);
var dateFormat = moment(date).format("HH:mm");
if (!result.includes(dateFormat)) {
result.push(dateFormat);
}
});
return result;
}
/**
*
* #param label
* #param entry
* #returns {___anonymous3118_3127}
*/
function dataCombinedLine(label, entry) {
var dataset = {
type: "line",
label: label,
lineTension: 0,
backgroundColor: "#4078A7",
borderCapStyle: "butt",
borderJoinStyle: "miter",
borderColor: "#4078A7",
pointRadius: 5,
pointBorderColor: "#4078A7",
pointBackgroundColor: "#FFFFFF",
pointBorderWidth: 3,
pointHoverRadius: 5,
pointHoverBackgroundColor: "#FFFFFF",
pointHoverBorderWidth: 3,
pointHitRadius: 5,
data: dataCombinedLineFromEntries(entry),
yAxisID : "y-axis-0",
fill: false
}
return dataset;
}
/**
*
* #param label
* #param entry
* #returns {___anonymous3299_3308}
*/
function dataCombinedBar(label, entry) {
var dataset = {
type: "bar",
label: label,
backgroundColor: "#239471",
borderCapStyle: "butt",
borderJoinStyle: "miter",
borderColor: "#239471",
data: dataCombinedBarFromEntries(entry),
yAxisID : "y-axis-1"
}
return dataset;
}
/**
*
* #param entry
* #returns {Array}
*/
function dataCombinedLineFromEntries(entry) {
var result = [];
var entryMeasures = entry.split("-")[0];
var entryMeasuresArray = entryMeasures.split(";");
entryMeasuresArray.forEach(function(entry) {
var entryPair = entry.split(",");
var date = parseFloat(entryPair[0]);
var value = entryPair[1];
var data = {
x: moment(date).format("HH:mm"),
y: entryPair[1]
}
result.push(data);
});
return result;
}
/**
*
* #param entry
* #returns {Array}
*/
function dataCombinedBarFromEntries(entry) {
var result = [];
if (entry.indexOf("-") >= 0) {
var entryInsulins = entry.split("-")[1];
var entryInsulinsArray = entryInsulins.split(";");
entryInsulinsArray.forEach(function(entry) {
var entryPair = entry.split(",");
var date = parseFloat(entryPair[0]);
var value = entryPair[1];
var data = {
x: moment(date).format("HH:mm"),
y: entryPair[1]
}
result.push(entryPair[1]);
});
}
return result;
}
With this code i managed to put both datasets into one chart, but there are two problems left. The first problem is that the first and the last bar are overlapping with the yAxis:
How can I disable the overlap?
The second problem remaining is the following: The line data and the bar data arent always matching. That means: If i have a line data entry for 08:00 o'clock that does not mean that there is a bar data entry for 08:00 o'clock. Same counts the other way: if there is a bar data for 12:00 o'clock it does not mean that there is a line data matching for 12:00 o'clock. There can be X data entries for the line data but Y data entries for the bar data. For that i created x and y values for the line data:
entryMeasuresArray.forEach(function(entry) {
var entryPair = entry.split(",");
var date = parseFloat(entryPair[0]);
var value = entryPair[1];
var data = {
x: moment(date).format("HH:mm"),
y: entryPair[1]
}
result.push(data);
});
This is working perfectly for the line data. But unfortunately i could not find such an option for the bar data. The bar data does not accept x and y values, it only accepts the y value:
entryInsulinsArray.forEach(function(entry) {
var entryPair = entry.split(",");
var date = parseFloat(entryPair[0]);
var value = entryPair[1];
var data = {
x: moment(date).format("HH:mm"),
y: entryPair[1]
}
result.push(entryPair[1]);
});
So how can i define x and y values for the bar data as i can define them for the line data?
EIDT
Im using the latest version 2.1.6
EDIT 2
Here a JSFiddle to demonstrate the problems
For the first problem :
How can I disable the overlap?
xAxes: [{
position: "bottom",
//type: "time", // erase this line
time: {
unit: "hour",
format: "HH:mm",
tooltipFormat: "HH:mm",
displayFormats: {
hour: "HH:mm",
day: "HH:mm",
week: "HH:mm",
month: "HH:mm",
quarter: "HH:mm",
year: "HH:mm"
}
}
}],
In the XAxes erase the line type: "time", this option imply that the graph has to start in zero without margin.
The second problem:
I think the best way to represent your data:
var data = [
{ x: "08:00", y_line: "110", y_bar: "30"},
{ x: "09:00", y_line: "120", y_bar: "35"},
{ x: "10:00", y_line: "130", y_bar: null},
{ x: "11:00", y_line: "140", y_bar: 45}
];
With this representation you force that each "time" has two measurements, one for the bar and one for the line that can have a numerical value or a null value.
Then with some functions you can get the sets:
function getLine(){
var arr = [];
data.forEach(function(entry) {
var data = { x: entry.x, y: entry.y_line}
arr.push(data);
});
return arr;
}
function getBar(){
var arr = [];
data.forEach(function(entry) {
arr.push(entry.y_bar);
});
return arr;
}
function getLabels(){
var arr = [];
data.forEach(function(entry) {
arr.push(entry.x);
});
return arr;
}
Then you introduce the values in your configuration like this:
{
type: "bar",
label: labelInsulin,
backgroundColor: "#239471",
borderCapStyle: "butt",
borderJoinStyle: "miter",
borderColor: "#239471",
data: getBar(), // like this
yAxisID : "y-axis-1"
}
If a "bar" has value null it doesn't appear. And because the "bar" has the same number of elements than the "line" they always match.

Restacking cumulative columns in Highcharts marimekko charts

I've got a basic variable width column chart (aka Marimekko) set up using Highcharts but am having trouble getting it to restack the columns properly to eliminate the data gap once a series has been removed or hidden.
JSFIDDLE DEMO <-- I've set up a demo of the issue here.
You'll notice clicking on a legend item removes the series from the chart, but it also removes all of the following data points in the array (i.e. clicking on series C removes series C, D, and E whereas it should redraw to A-B-D-E). Since the y-axis data is meant to display a cumulative sum of all series, these should re-shuffle as adjacent columns with no gaps. How can I get this to render properly?
THIS POST uses similar demo code and attempting to solve the same problem, however the answer is somewhat elusive and I am unable to get it working.
Thanks in advance!
$(function () {
var dataArray = [
{ name: 'A', x: 200, y: 120 },
{ name: 'B', x: 380, y: 101 },
{ name: 'C', x: 450, y: 84 },
{ name: 'D', x: 198, y: 75 },
{ name: 'E', x: 95, y: 55 }
];
function makeSeries(listOfData) {
var sumX = 0.0;
for (var i = 0; i < listOfData.length; i++) {
sumX += listOfData[i].x;
}
var allSeries = []
var x = 0.0;
for (var i = 0; i < listOfData.length; i++) {
var data = listOfData[i];
allSeries[i] = {
name: data.name,
data: [
[x, 0], [x, data.y],
{
x: x + data.x / 2.0,
y: data.y,
dataLabels: { enabled: false, format: data.x + ' x {y}' }
},
[x + data.x, data.y], [x + data.x, 0]
],
w: data.x,
h: data.y
};
x += data.x + 0;
}
return allSeries;
}
$('#container').highcharts({
chart: { type: 'area' },
xAxis: {
tickLength: 0,
labels: { enabled: true}
},
yAxis: {
title: { enabled: false}
},
plotOptions: {
series: {
events: {
legendItemClick: function () {
var pos = this.index;
var sname = this.name;
var chart = $('#container').highcharts();
while(chart.series.length > 0) {
chart.series[pos].remove(true);
}
dataArray[pos]= { name: sname, x: 0, y: 0 };
chart.series[0].setData(dataArray);
}
}
},
area: {
lineWidth: 0,
marker: {
enabled: false,
states: {
hover: { enabled: false }
}
}
}
},
series: makeSeries(dataArray)
});
});

Categories

Resources