Related
I have a problem when generating a bar chart :
I don't understand why 50%+50% doesn't smoke 100% of the seat? Config seems to be good ? Did i miss something?
Here the code :
new Chart(draw, {
type: 'bar',
data: {
labels: [currentYear],
datasets: [
{
label: 'Legend 1',
data: [50],
backgroundColor: '#fdfd96', // yellow
},
{
label: 'Legend 2',
data: [50],
backgroundColor: '#77b5fe', // blue
},
],
},
options: {
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
},
},
animation: {
onComplete: function () {
saveChartAsImage(
this.toBase64Image(),
currentYear,
companyId,
'actif',
manualMode,
);
},
},
},
});
Your code and configuration looks correct and works ( demo seen below ) but if you want to be on the save side yo can add the properties max:100 to the y axis, this could fix the hight issue.
Here the demo:
const data = {
labels: [2022],
datasets: [{
label: 'Legend 1',
data: [50],
backgroundColor: '#fdfd96', // yellow
},
{
label: 'Legend 2',
data: [50],
backgroundColor: '#77b5fe', // blue
},],
};
const config = {
type: 'bar',
data: data,
options: {
maintainAspectRatio: false,
animation: {
onComplete: function () {
let img = document.createElement('img')
let url = this.toBase64Image()
img.src = url
document.querySelector('#imagePreview').append(img);
}
},
scales: {
x: {
stacked: true,
},
y: {
stacked: true,
max:100
},
}}
};
var cart = new Chart(
document.getElementById('chart'),
config
);
<script src="//cdn.jsdelivr.net/npm/chart.js"></script>
<div class="chart" style="height:184px; width:350px;">
<canvas id="chart" ></canvas>
</div>
<b> preview Image </b>
<div id="imagePreview"></div>
Update screenshot of result:
Update:
After testing the assumtion must be, that the save function is defective or there is some sort of race condition with a different chart. Since createing a image onComplete creates a correct images, in the updated demo.
I'm assuming the wrong visuals have to to with the animation, not being finished when the image is created, if this is so, one could workaround this fact (or just to test the theory), with using a timeout for creating the image, something like this
onComplete: function () {
setTimeout( () => {
saveChartAsImage(
this.toBase64Image(),
currentYear,
companyId,
'actif',
manualMode,
);
}, 1000); // <-- One Second should be enough for the animation to end
}
I'm trying to create a bar chart that is grouped by the dataset rather than the label in chartjs3 and I'm having no luck. Before I switch over to building in D3, I wanted to check if this achievable within the confines of ChartJS.
Here is a link to a fiddle where I've been playing around with using different dataset structures and options from the Bar chart docs. I suspect that this is outside of the scope of the charting library, or is within the scope, but requires some custom components to be made – I would appreciate if anyone could direct me on what in particular I would need to extend (e.g. is it a case of a custom axes? or more?).
https://jsfiddle.net/f34ucs76/2/
const data = {
labels: [
'2000','2010','2020',
// 'Frogs','Monkeys','Squirrels','Bats'
],
datasets: [
{
label: 'Frogs',
data: [30.2,20.8,36.2],
backgroundColor: 'red',
//stack: 'Frogs',
},
{
label: 'Monkeys',
data: [16.3,13.0,22.3],
backgroundColor: 'blue',
//stack: 'Monkeys',
},
{
label: 'Squirrels',
data: [5.8,3.1,14.9],
backgroundColor: 'cyan',
//stack:'Squirrels',
},
{
label: 'Bats',
data: [0.1,3.6,2.6],
backgroundColor: 'aquamarine',
//stack:'Bats',
},
],
}
const options = {
maintainAspectRatio: false,
responsive: true,
interaction: {
intersect: false,
mode: 'index',
},
plugins: {
title: {
display: false,
},
subtitle: {
display: true,
align: 'start',
text: ['Source: Animals Index, June 2022'],
font: {
size: 12,
style: 'italic',
},
position: 'bottom',
padding: {
top: 20,
},
},
legend: {
display: true,
position: 'bottom',
},
tooltip: {
enabled: true,
},
},
scales: {
x: {
grid: {
display: false,
},
},
y: {
title: {
display: true,
text: 'Horsepower',
},
},
},
}
const mychart = new Chart(
document.getElementById('mychart'),
{
type: 'bar',
data: data,
options: options,
}
);
Your problem can be solved with Chart.js but the labels and the single dataset need to be generated.
Further you need to define your own legend by defining a plugins.legend.labels.generateLabels together with with a plugins.legend.labels.onClick function.
For further information, consult the Legend page from the Chart.js. documentation.
Please take a look at your amended and runnable code below and see how it works.
const baseData = {
labels: ['2000','2010','2020'],
datasets: [
{ label: 'Frogs', data: [30.2, 20.8, 36.2], bgColor: 'red', hidden: false },
{ label: 'Monkeys', data: [16.3, 13.0, 22.3], bgColor: 'blue', hidden: false },
{ label: 'Squirrels', data: [5.8,3.1, 14.9], bgColor: 'cyan', hidden: false },
{ label: 'Bats', data: [0.1, 3.6, 2.6], bgColor: 'aquamarine', hidden: false }
]
};
const iLastDs = baseData.datasets.length - 1;
const data = {
labels: baseData.datasets
.map(() => baseData.labels)
.map((labels, i) => i < iLastDs ? [...labels, null] : labels)
.flatMap(v => v),
datasets: [{
data: baseData.datasets
.map(ds => ds.data)
.map((data, i) => i < iLastDs ? [...data, null] : data)
.flatMap(v => v),
backgroundColor: baseData.datasets
.map(ds => ds.data.map(v => ds.bgColor))
.map((bgColors, i) => i < iLastDs ? [...bgColors, null] : bgColors)
.flatMap(v => v),
categoryPercentage: 1,
barPercentage: 0.9
}]
};
const options = {
maintainAspectRatio: true,
responsive: true,
interaction: {
intersect: true,
mode: 'index',
},
plugins: {
legend: {
position: 'bottom',
labels: {
generateLabels: chart => baseData.datasets.map((ds, i) => ({
datasetIndex: i,
text: ds.label,
fillStyle: ds.bgColor,
strokeStyle: 'lightgray',
hidden: baseData.datasets[i].hidden
}))
},
onClick: (event, legendItem, legend) => {
baseData.datasets[legendItem.datasetIndex].hidden = !baseData.datasets[legendItem.datasetIndex].hidden;
const iFirstValue = legendItem.datasetIndex + legendItem.datasetIndex * baseData.labels.length;
for (let i = iFirstValue; i < iFirstValue + baseData.labels.length; i++) {
legend.chart.toggleDataVisibility(i);
}
legend.chart.update();
}
},
tooltip: {
callbacks: {
title: ctx => {
const dsIndex = Math.floor(ctx[0].dataIndex / baseData.datasets.length);
return baseData.datasets[dsIndex].label + ' / ' + ctx[0].label;
}
}
}
},
scales: {
x: {
grid: {
display: false
}
},
y: {
title: {
display: true,
text: 'Horsepower',
}
}
}
};
new Chart('mychart', {
type: 'bar',
data,
options
});
span {
font-style: italic;
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<canvas id="mychart" height="100"></canvas>
<span>Source: Animals Index, June 2022</span>
I have an issue when I want to display a chart on my web page using django and highcharts. This is my detail.html file.
I have an error called property assignment expected on the side of my curly brackets here :
_dateList={{dateList|safe}};
_price={{price.room.actual_rate.amount}};
_availability={{availability}};
Here is the all file
<h1>{{property.name}}</h1>
<h2>{{roomtype.name}}</h2>
<div id="container"></div>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script>
_dateList={{dateList|safe}};
_price={{price.room.actual_rate.amount}};
_availability={{availability}};
Highcharts.chart('container', {
title: {
text: 'Pricing model prevision'
},
xAxis: {
categories: _dateList
},
yAxis: [{
title: {
text: 'Price',
style: {
color: Highcharts.getOptions().colors[2]
}
},
labels: {
style: {
color: Highcharts.getOptions().colors[2]
}
}
}, {
title:{
text:'Occupancy',
style:{
color: Highcharts.getOptions().colors[0]
}
},
labels:{
style:{
color: Highcharts.getOptions().colors[0]
}
},
opposite: true
}],
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
plotOptions: {
series: {
label: {
connectorAllowed: false
},
pointStart: 2010
}
},
series: [{
name: 'price',
data: _price
}, {
name: 'availabilty',
data: _availability
}],
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
});
</script>
<ul>
{% for day in dayList %}
{% if day.availability.room %}
<li>{{day.date}}:{{day.allotment}}:{{day.pricing.room.actual_rate.amount}} </li>
{% else %}
<li>{{day.date}}:0 </li>
{% endif %}
{% endfor %}
</ul>
Can you help me with this issue?
thank you for your help,
Best
If you add quotation marks, as shown below, it should work:
_dateList='{{dateList|safe}}';
Without quotation marks, it is interpreted as a variable. With quotation marks, it is interpreted as a string.
I am using chart.js library. I am creating a graph and want to show dates in x-axis like here: http://www.chartjs.org/samples/latest/scales/time/line.html
I have provided the same configuration (except the date format of graph data) for graph as the above example provides but my graph showing time i.e 2 am, 2 am, .. instead of dates i.e 2018-02-01, 2018-02-10, ...
For date formatting i am using the moment.js library recommended by Chart.js
I am using following code:
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
</head>
<body>
<div style="width:75%;">
<canvas id="canvas"></canvas>
</div>
<script>
var timeFormat = 'YYYY-MM-DD';
var config = {
type: 'line',
data: {
datasets: [{
label: "Thi is graph label",
backgroundColor: "rgb(54, 162, 235)",
borderColor: "rgb(255, 159, 64)",
fill: false,
data: [{
x: moment("2010-03-01").format(timeFormat),
y: 0.668525
}, {
x: moment("2010-03-02").format(timeFormat),
y: 0.668827
}],
}]
},
options: {
title: {
text: "This is title"
},
scales: {
xAxes: [{
type: "time",
time: {
parser: timeFormat,
tooltipFormat: 'll HH:mm'
},
scaleLabel: {
display: true,
labelString: 'Date'
}
},],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'value'
}
}]
},
}
};
window.onload = function () {
var ctx = document.getElementById("canvas").getContext("2d");
console.log(config);
window.myLine = new Chart(ctx, config);
};
</script>
</body>
</html>
<html>
<head>
<title>Line Chart</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
<style>
canvas {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
</style>
</head>
<body>
<div style="width:75%;">
<canvas id="canvas"></canvas>
</div>
<br>
<br>
<button id="randomizeData">Randomize Data</button>
<button id="addDataset">Add Dataset</button>
<button id="removeDataset">Remove Dataset</button>
<button id="addData">Add Data</button>
<button id="removeData">Remove Data</button>
<script>
var timeFormat = 'MM/DD/YYYY HH:mm';
function newDate(days) {
return moment().add(days, 'd').toDate();
}
function newDateString(days) {
return moment().add(days, 'd').format(timeFormat);
}
var color = Chart.helpers.color;
var config = {
type: 'line',
data: {
labels: [ // Date Objects
newDate(0),
newDate(1),
newDate(2),
newDate(3),
newDate(4),
newDate(5),
newDate(6)
],
datasets: [{
label: 'My First dataset',
backgroundColor: color(window.chartColors.red).alpha(0.5).rgbString(),
borderColor: window.chartColors.red,
fill: false,
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'My Second dataset',
backgroundColor: color(window.chartColors.blue).alpha(0.5).rgbString(),
borderColor: window.chartColors.blue,
fill: false,
data: [
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor(),
randomScalingFactor()
],
}, {
label: 'Dataset with point data',
backgroundColor: color(window.chartColors.green).alpha(0.5).rgbString(),
borderColor: window.chartColors.green,
fill: false,
data: [{
x: newDateString(0),
y: randomScalingFactor()
}, {
x: newDateString(5),
y: randomScalingFactor()
}, {
x: newDateString(7),
y: randomScalingFactor()
}, {
x: newDateString(15),
y: randomScalingFactor()
}],
}]
},
options: {
title: {
text: 'Chart.js Time Scale'
},
scales: {
xAxes: [{
type: 'time',
time: {
format: timeFormat,
// round: 'day'
tooltipFormat: 'll HH:mm'
},
scaleLabel: {
display: true,
labelString: 'Date'
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'value'
}
}]
},
}
};
window.onload = function() {
var ctx = document.getElementById('canvas').getContext('2d');
window.myLine = new Chart(ctx, config);
};
document.getElementById('randomizeData').addEventListener('click', function() {
config.data.datasets.forEach(function(dataset) {
dataset.data.forEach(function(dataObj, j) {
if (typeof dataObj === 'object') {
dataObj.y = randomScalingFactor();
} else {
dataset.data[j] = randomScalingFactor();
}
});
});
window.myLine.update();
});
var colorNames = Object.keys(window.chartColors);
document.getElementById('addDataset').addEventListener('click', function() {
var colorName = colorNames[config.data.datasets.length % colorNames.length];
var newColor = window.chartColors[colorName];
var newDataset = {
label: 'Dataset ' + config.data.datasets.length,
borderColor: newColor,
backgroundColor: color(newColor).alpha(0.5).rgbString(),
data: [],
};
for (var index = 0; index < config.data.labels.length; ++index) {
newDataset.data.push(randomScalingFactor());
}
config.data.datasets.push(newDataset);
window.myLine.update();
});
document.getElementById('addData').addEventListener('click', function() {
if (config.data.datasets.length > 0) {
config.data.labels.push(newDate(config.data.labels.length));
for (var index = 0; index < config.data.datasets.length; ++index) {
if (typeof config.data.datasets[index].data[0] === 'object') {
config.data.datasets[index].data.push({
x: newDate(config.data.datasets[index].data.length),
y: randomScalingFactor(),
});
} else {
config.data.datasets[index].data.push(randomScalingFactor());
}
}
window.myLine.update();
}
});
document.getElementById('removeDataset').addEventListener('click', function() {
config.data.datasets.splice(0, 1);
window.myLine.update();
});
document.getElementById('removeData').addEventListener('click', function() {
config.data.labels.splice(-1, 1); // remove the label first
config.data.datasets.forEach(function(dataset) {
dataset.data.pop();
});
window.myLine.update();
});
</script>
</body>
</html>
You need to set:
scales: {
xAxes: [
{
.....
ticks: {
source: 'date'
},
}
......
],
I have a container with three items:
ombrelloneButton = Ext.create('Ext.Button', {
id: 'btnOmbr',
iconMask: true,
iconCls: 'action',
text: 'Ombrellone'
});
lettinoButton = Ext.create('Ext.Button', {
id: 'btnLett',
iconMask: true,
iconCls: 'action',
text: 'Lettino'
});
toolbarPostazione = Ext.create('Ext.Toolbar',{
layout: {
pack: 'center'
}, // layout
ui: 'plain',
items: [ombrelloneButton,
lettinoButton]
});
Ext.define('appTrial.view.Postazione.Postazione',{
extend: 'Ext.form.Panel',
xtype: 'Postazione',
alias: 'widget.Postazione',
controllers:['AssociaAttivitaController'],
models : ['appTrial.model.AttivitaModel'],
config : {
id : 'PostazioneId',
title : 'Welcome',
resizable : false,
collapsible : true,
bodyPadding : '5',
buttonAlign : 'center',
border : false,
trackResetOnLoad : true,
items : [{
docked: 'top',
xtype: 'titlebar',
title: 'Welcome to My New App!!!'
},
{
xtype: 'container',
name: 'mainContainer',
id: 'postazioneContainer',
layout: {
type: 'vbox',
align: 'center',
pack: 'center'
},
//width : '100%',
items : [{
layout: {
pack: 'center'
},
html :'<p style="color: red; text-align: center; font-size: 20px" >Complimenti!</p><br><p style="text-align: center; font-size: 16px">Sei stato associato alla attivita '+dummyAttivita.get('nomeAttivita')+'!</p>' +
'<br><p style="text-align: center; font-size: 16px">Ora associa la tua postazione:</p>',
margin: '80 0 50 0'
},
toolbarPostazione,
{
xtype: 'PostazioniList',
title:'PostazioniAssociate',
id: 'PostazioniAssociate'
}
]
}]
}
});
The first two of them are showed (html text and toolbar), while the PostazioniList is not showed.
It is done like this (List.js):
Ext.define('appTrial.view.Postazione.List', {
extend: 'Ext.List',
xtype: 'PostazioniList',
alias: 'widget.PostazioniList',
itemTpl: '<div>{tipoPostazione} num.{numPostazione}</div>',
data: [{
tipoPostazione: 'Ombrellone',
numPostazione: '5'
},
{
tipoPostazione: 'Ombrellone',
numPostazione: '37'
},
{
tipoPostazione: 'Lettino',
numPostazione: '46d'
}]
});
Could it be a html problem?
I don't understand also why I don't get any error, just it is hidden...
Thanks in advance