The low and high points on this chart are getting cut off, is there any way to fix this without knowing what numbers will be in the data?
I've seen other people create some padding with the chart's minimum and maximum values, but I don't know what the values will be beforehand.
Chart:
A similar example suffering from the same problem is shown here: http://codepen.io/erose/pen/LNwdQO/
Here's the HTML:
<div class="chart-container">
<canvas id="chart"></canvas>
</div>
Here's the CSS:
.chart-container {
width: 493px;
height: 83px;
}
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
and here the JS used to create the above chart:
var ctx = $("#chart");
Chart.defaults.global.responsive = true;
Chart.defaults.global.maintainAspectRatio = false;
Chart.defaults.global.legend.display = false;
Chart.defaults.global.tooltips.backgroundColor = "lightblue";
Chart.defaults.global.tooltips.bodyFontFamily = "sans-serif";
Chart.defaults.global.tooltips.bodyFontSize = 20;
Chart.defaults.global.tooltips.bodyColor = "#95989a";
Chart.defaults.global.tooltips.bodyAlign = "left";
Chart.defaults.global.tooltips.titleFontSize = 0;
Chart.defaults.global.tooltips.titleMarginBottom = 0;
Chart.defaults.global.tooltips.footerMarginTop = 0;
Chart.defaults.global.tooltips.cornerRadius = 12;
Chart.defaults.global.tooltips.caretSize = 10;
Chart.defaults.global.tooltips.xPadding = 20;
Chart.defaults.global.tooltips.yPadding = 10;
Chart.defaults.scale.gridLines.color = 'white';
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [" ", "", "", "", "", "", "", "", "", " "],
datasets: [{
label: '$',
data: [100,100,100,100,0,100,100,100,100,100],
fill: false,
borderWidth: 1,
borderColor: "#2f75c1",
borderCapSytle: "round",
pointBorderColor: "#2f75c1",
pointBackgroundColor: "#2f75c1",
pointBorderWidth: 5,
pointHoverRadius: 10,
}]
},
options: {
scales: {
yAxes: [{
gridLines: {
display: false
},
scaleLabel: {
display: false
},
scaleLkneColor: 'white',
ticks: {
display: false
}
}],
xAxes: [{
gridLines: {
display: false
},
scaleLabel: {
display: false
},
// ticks: {
// display: false
// }
}]
}
}
});
From reading your question I believe you not only want the for the circle to not be cut off but you would like some extra padding inside the chart.
For that I would structure this a little different:
var ctx = $("#chart");
Chart.defaults.global.responsive = true;
Chart.defaults.global.maintainAspectRatio = false;
Chart.defaults.global.legend.display = false;
Chart.defaults.global.tooltips.backgroundColor = "lightblue";
Chart.defaults.global.tooltips.bodyFontFamily = "sans-serif";
Chart.defaults.global.tooltips.bodyFontSize = 20;
Chart.defaults.global.tooltips.bodyColor = "#95989a";
Chart.defaults.global.tooltips.bodyAlign = "left";
Chart.defaults.global.tooltips.titleFontSize = 0;
Chart.defaults.global.tooltips.titleMarginBottom = 0;
Chart.defaults.global.tooltips.footerMarginTop = 0;
Chart.defaults.global.tooltips.cornerRadius = 12;
Chart.defaults.global.tooltips.caretSize = 10;
Chart.defaults.global.tooltips.xPadding = 20;
Chart.defaults.global.tooltips.yPadding = 10;
Chart.defaults.scale.gridLines.color = 'white';
var getData = [100,100,100,100,0,100,100,100,100,100];
var getLabels = ["", "", "", "", "", "", "", "", "", ""];
var minNum = function(array){
return Math.min.apply( Math, array )-10;
}
var maxNum = function(array){
return Math.max.apply( Math, array )+10;
}
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: getLabels,
datasets: [{
label: '$',
data: getData,
fill: false,
borderWidth: 1,
borderColor: "#2f75c1",
borderCapSytle: "round",
pointBorderColor: "#2f75c1",
pointBackgroundColor: "#2f75c1",
pointBorderWidth: 5,
pointHoverRadius: 10,
}]
},
options: {
scales: {
yAxes: [{
gridLines: {
display: false
},
scaleLabel: {
display: false
},
scaleLkneColor: 'white',
ticks: {
suggestedMin: minNum(getData),
suggestedMax: maxNum(getData),
}
}],
xAxes: [{
gridLines: {
display: false
},
scaleLabel: {
display: false
},
// ticks: {
// display: false
// }
}]
}
}
});
.chart-container {
width: 493px;
height: 83px;
}
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.bundle.min.js"></script>
<div class="chart-container">
<canvas id="chart"></canvas>
</div>
2 Important changes
I create a getData var to hold the array this way the array can be formatted however you like the function does not care it just looks for getData and expects an array.
I created a minNum and maxNum function to go through the array and select either the lowest or highest number then call that inside the ticker you can find more on this at ChartJS Scales
Related
I need to plot a single value in line chart. Currently i am using charts.JS library for line graph purpose.
The data will be varied some times i'll get the single data inside the data set at that time i need to plot the single value with line in the line chart.
I tried with the charts.js annotation plugin but it wasn't met my requirements. which is like it wis overlapping the plotted point in the graph area.
CODE WHICH I HAD TRIED
createLineChart() {
this.lineChart = new Chart(this.lineCanvas.nativeElement, {
type: "line",
data: {
labels:[],
datasets: [
{
fill: false,
backgroundColor: "#0168FF",
borderColor: "#0168FF",
pointBackgroundColor: "white", // wite point fill
pointBorderWidth: 1, // point border width
lineTension: 0,
pointBorderColor: "blue",
pointRadius: 4,
},
],
},
options: {
scales: {
yAxes: [
{
ticks: {
padding: 20,
beginAtZero: true,
min: 0,
stepSize: 100,
},
gridLines: {
drawBorder: false,
},
},
],
xAxes: [
{
// offset: true,
ticks: {
display: false,
//beginAtZero: true,
min: 0,
},
gridLines: {
zeroLineColor: "transparent",
drawBorder: false,
display: false,
},
//offset:true,
},
],
legend: {
display: false,
},
tooltips: {
enabled: false,
},
},
drawTime: "afterDraw", // (default)
} as ChartOptions,
// plugins: [ChartAnnotation]
},
});
}
To generate dynamic data and plot in the graph area.
generateRandomDataSet(size) {
let yaxisArr = [];
let xaxisArr = [];
let random_data:any = this.getRandomData(size)
let maxYTickVal = Math.max.apply(Math, random_data.map((val) => {return val.yaxis}));
let maxVal = Math.ceil((maxYTickVal+1) / 10) * 10
for(let data of random_data) {
yaxisArr.push(data.yaxis)
xaxisArr.push(data.xaxis)
}
console.log("X-Axis array values : "+xaxisArr)
console.log("Y-Axis array values : "+yaxisArr)
this.lineChart.data.datasets[0].data = yaxisArr
this.lineChart.config.data.labels = []
this.lineChart.config.data.labels = xaxisArr
this.lineChart.config.options.scales.yAxes[0].ticks.max =maxVal
this.lineChart.config.options.scales.yAxes[0].ticks.stepSize = maxVal/2
this.lineChart.update()
}
getRandomData(arraySize) {
let data = []
for(var i=1; i<=arraySize; i++) {
let number = Math.floor(Math.random() * 200) + 1
data.push({'xaxis':i,'yaxis':number})
}
return data
}
with the above code i am getting like
what i need to have
You can define an animation.onComplete function as follows to draw the line in case a single data value is present.
animation: {
onComplete: e => {
var ctx = chart.chart.ctx;
var data = chart.config.data.datasets[0].data;
if (data[0] == null) {
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var y = yAxis.getPixelForValue(data[1]);
ctx.save();
ctx.globalCompositeOperation='destination-over';
ctx.strokeStyle = 'blue'
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
ctx.restore();
}
}
},
This function expects the data array to be of format [null, <value>, null] in case a single value is present, otherwise it will be hard to horizontally center the data point (see this answer). It's up to you to change the generateRandomDataSet() function in a way that it provides such data.
Please have a look at your changed code below.
const chart = new Chart('line-chart', {
type: "line",
data: {
labels: ['', 'A', ''],
datasets: [{
data: [null, 120, null],
fill: false,
backgroundColor: "#0168FF",
borderColor: "#0168FF",
pointBackgroundColor: "white",
pointBorderWidth: 1,
lineTension: 0,
pointBorderColor: "blue",
pointRadius: 4,
}],
},
options: {
legend: {
display: false
},
tooltips: {
enabled: false
},
animation: {
onComplete: e => {
var ctx = chart.chart.ctx;
var data = chart.config.data.datasets[0].data;
if (data[0] == null) {
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
var y = yAxis.getPixelForValue(data[1]);
ctx.save();
ctx.globalCompositeOperation='destination-over';
ctx.strokeStyle = 'blue'
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(xAxis.left, y);
ctx.lineTo(xAxis.right, y);
ctx.stroke();
ctx.restore();
}
}
},
scales: {
yAxes: [{
ticks: {
padding: 20,
min: 0,
stepSize: 100
},
gridLines: {
drawBorder: false
}
}],
xAxes: [{
ticks: {
display: false
},
gridLines: {
zeroLineColor: "transparent",
drawBorder: false,
display: false
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="line-chart" height="80"></canvas>
I'm using the HorizontalBar option of the Chartjs plugin and I have values between -15 and 115. When my percentage value is 0.75 I'd like the bar to fill from -15 to 0.75.
I have set the properties beginAtZero false (which I believe it only works in Y axis..) and fill as true but it does not work.
datasets: [
{
data: [percentage],
fill: true,
backgroundColor: 'rgba(0, 0, 0, 1)'
}]
....
options:
{
scales:
{
xAxes: [
{
ticks:
{
beginAtZero: false,
min: min,
max: max
}
}],
}
}
As you may see in this JSFiddle the black bar starts at 0 and should start at -15.
This can be done with a floating bar since Chart.js v2.9.0, a feature that was merged into chartjs:master with pull request #6056. Individual bars can now be specified with the syntax [min, max].
<html>
<head>
<title>Floating Bar</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
</style>
</head>
<body>
<div>
<canvas id="canvas" height="50"></canvas>
</div>
<script>
var percentage = 0.92;
var min = -15;
var max = 115;
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myBar = new Chart(ctx, {
type: 'horizontalBar',
data: {
datasets: [{
data: [[min, percentage]],
fill: true,
backgroundColor: 'rgba(0, 0, 0, 1)'
}]
},
options: {
title: {
display: false
},
tooltips: {
mode: 'index',
intersect: false
},
legend: {
display: false
},
responsive: true,
scales: {
xAxes: [{
ticks: {
min: min,
max: max
}
}],
}
}
});
};
</script>
</body>
</html>
I'm having some issues when trying to update a chart's data using $scope.
I know there's a function to update charts myChart.update(); but I can't get to update the char when I put it in a $scope.
The following code gets the chart's data and then tries to update the chart. The problem comes at $scope.lineChart.update();. It looks like chartjs can't detect any changes.
The following code is executed after triggering a select, so the chart has an initial data and the following code just tries to update it.
This does not work: $scope.lineChart.update();
$scope.getLineChartMaxData().then(function () {
$scope.getLineChartMinData().then(function () {
$scope.lineChart.update();
});
});
The chart function:
$scope.fillLineChart = function () {
console.log("FILLING LINE CHART");
const brandProduct = 'rgba(0,181,233,0.5)'
const brandService = 'rgba(0,173,95,0.5)'
var data1 = $scope.lineChartMaxWeekData;
var data2 = $scope.lineChartMinWeekData;
var maxValue1 = Math.max.apply(null, data1)
var maxValue2 = Math.max.apply(null, data2)
var minValue1 = Math.min.apply(null, data1)
var minValue2 = Math.min.apply(null, data2)
var maxValue;
var minValue;
if (maxValue1 >= maxValue2) {
maxValue = maxValue1;
} else {
maxValue = maxValue2;
}
if (minValue1 >= minValue2) {
minValue = minValue2;
} else {
minValue = minValue1;
}
$scope.minValue = minValue;
$scope.maxValue = maxValue;
var ctx = document.getElementById("recent-rep-chart");
if (ctx) {
ctx.height = 250;
$scope.lineChart = new Chart(ctx, {
type: 'line',
data: {
labels: $scope.lineChartMaxWeekLabels,
datasets: [{
label: 'Valor',
backgroundColor: brandService,
borderColor: 'transparent',
pointHoverBackgroundColor: '#fff',
borderWidth: 0,
data: data1
},
{
label: 'My Second dataset',
backgroundColor: brandProduct,
borderColor: 'transparent',
pointHoverBackgroundColor: '#fff',
borderWidth: 0,
data: data2
}
]
},
options: {
maintainAspectRatio: true,
legend: {
display: false
},
responsive: true,
scales: {
xAxes: [{
gridLines: {
drawOnChartArea: true,
color: '#f2f2f2'
},
ticks: {
fontFamily: "Poppins",
fontSize: 12
}
}],
yAxes: [{
ticks: {
beginAtZero: true,
maxTicksLimit: 5,
stepSize: 50,
max: maxValue,
fontFamily: "Poppins",
fontSize: 12
},
gridLines: {
display: true,
color: '#f2f2f2'
}
}]
},
elements: {
point: {
radius: 0,
hitRadius: 10,
hoverRadius: 4,
hoverBorderWidth: 3
}
}
}
});
}
};
UPDATE: $scope.lineChart.destroy(); works well, but I don't want to destroy the chart and build it again because it is built with another sizes.
I have these bar charts that will sometimes show zero values to the user. I'd like to show a bit of the bar chart so it does not look completely empty, but the data is connected to the visual representation of the bar. Is there any way I could have the top number say zero but the value be 3(or something small) in each column? Here is the code and a screenshots. One screenshot has data, the other is zero. I'd like the zero graph to show just a bit of the orange and green when at zero. Thanks
<canvas id="bar-chart" width="900" height="350"></canvas>
<script type="text/javascript">
var ctx = document.getElementById("bar-chart");
debugger;
var data = {
labels: ["Page Views", "Data Requests"],
datasets: [{
data: [<?php echo $databaseClass->totalViewsSelectedMonth($user_id, $year, 1);
?>, <?php
echo $databaseClass->isRfYearMonth($user_id, $year, 1);
?>],
backgroundColor: ["orange", "green"]
}]
}
var myChart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
"hover": {
"animationDuration": 0
},
"animation": {
"duration": 1,
"onComplete": function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(bar, index) {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y - 5);
});
});
}
},
legend: {
"display": false
},
tooltips: {
"enabled": false
},
scales: {
yAxes: [{
display: false,
gridLines: {
display: false
},
ticks: {
max: Math.max(...data.datasets[0].data) + 20,
display: false,
beginAtZero: true
}
}],
xAxes: [{
gridLines: {
display: false
},
ticks: {
beginAtZero: true
}
}]
}
}
});
</script>
It looks like you can update the axes of your charts to a new default. So, using a modified form of their example, something like the following (modified to fit your code):
// ...
scales: {
yAxes: [{
display: false,
gridLines: {
display: false
},
ticks: {
max: Math.max(...data.datasets[0].data) + 20,
min: -3, // ADDED
display: false,
beginAtZero: true
}
}],
// ...
... would do what you're looking for - with the side benefit that 0 and 3 wouldn't look like the same value, the relative bar size should stay accurate.
Is it possible to make a fever chart using Charists.js or with another charing library?
Fever Chart example: Fever chart
The background can be a picture.
I used static series and overide the css.
It's not elegant, but it works.
Js:
var option = {
fullWidth: false,
axisX: {
high: 100,
low: 0,
type: Chartist.AutoScaleAxis,
onlyInteger: true,
scaleMinSpace: 10
},
axisY: {
high: 100,
low: 0,
scaleMinSpace: 10,
onlyInteger: true
},
series:{
'bg-green':{
showArea: true,
showLine: false,
showPoint: false
},
'bg-yellow':{
showArea: true,
showLine: false,
showPoint: false
},
'bg-red':{
showArea: true,
showLine: false,
showPoint: false
},
'fever':{
showArea: false,
showLine: false,
showPoint: true
}
}
};
var responsiveOptions = [];
var chart = {};
$scope.model = [];
var series = {
name: "Pulmao",
data: [],
};
var dataset = []; //here goes your dynamic data.
var bgGreen = {
name: "bg-green",
data:[ {x:4, y:0}, {x:100, y:90} ]
};
var bgYellow = {
name: "bg-yellow",
data:[ {x:0, y:10}, {x:100, y:110} ]
};
var bgRed = {
name: "bg-red",
data:[ {x:0, y:100}, {x:100, y:100} ]
};
dataset = {
series: [bgRed, bgYellow, bgGreen, series],
};
chart = new Chartist.Line('#feverChart', dataset, option,
responsiveOptions);
HTML
<div id="bufferChart" class="bufferchart ct-chart ct-minor-seventh"></div>
CSS
.bufferchart .ct-series-a .ct-area{
stroke: none;
fill-opacity: .6;
fill: #d70206;
}
.bufferchart .ct-series-b .ct-area{
stroke: none;
fill-opacity: .7;
fill: yellow;
}
.bufferchart .ct-series-c .ct-area{
stroke: none;
fill-opacity: .7;
fill: green;
}