I've created a chart in Chart.js that looks like this:
(Full code: https://codepen.io/LondonAppDev/pen/RwMBxPX)
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [{
label: 'Range',
data: [
{x: 'A', y: [100, 200]},
{x: 'B', y: [50, 120]}
],
backgroundColor: ['red']
}]
},
options: {
barThickness: 1,
}
});
I'm trying to style the bar so they have markers at the top and bottom like this:
I've looked into CSS but it won't work as the elements are within a canvas.
I'm wondering if there is a style option that would achieve this?
I think there are 2 options:
use Chart error bars plugin: https://github.com/sgratzl/chartjs-chart-error-bars
develop own plugin to do that.
In the below snippet, you can find the options 2 (own plugin)
var plugin = {
id: 'myPlugin',
afterDraw(chart, args) {
const ctx = chart.ctx;
ctx.save();
const meta = chart.getDatasetMeta(0);
for (const data of meta.data) {
const topStart = data.x - 20;
const topEnd = data.x + 20;
ctx.lineWidth = data.options.borderWidth;
ctx.strokeStyle = data.options.backgroundColor;
ctx.beginPath();
ctx.moveTo(topStart, data.y);
ctx.lineTo(topEnd, data.y);
ctx.moveTo(topStart, data.y + data.height);
ctx.lineTo(topEnd, data.y + data.height);
ctx.closePath();
ctx.stroke();
}
ctx.restore();
}
};
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
plugins: [plugin],
data: {
datasets: [{
label: 'Range',
data: [
{x: 'A', y: [100, 200]},
{x: 'B', y: [50, 120]}
],
backgroundColor: ['red']
}]
},
options: {
barThickness: 1,
}
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://npmcdn.com/chart.js#latest/dist/chart.min.js"></script>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
Related
I am using chart.js from a frontend react application. I need to create a plot with chart.js so that I can attach it to a powerpoint slide with pptxgen. This image does not have to be rendered visually, I just need to create it when the user requests to generate the ppt.
Chart needs a context, so I created a canvas element to act as such, then tried to render and export the base64 image that I would then proceed to feed into pptxgen:
let ctx = document.createElement("canvas")
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart: Chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
} )
chart.render()
console.log(chart.toBase64Image())
But all I obtain is "data:;" which looks to be an empty image.
Do you know how to make it render?
The only way to render a chart without you specifically adding it to the dom is by making use of the offscreen-canvas as explained here in the documentation of chart.js:
https://www.chartjs.org/docs/3.7.1/general/performance.html#parallel-rendering-with-web-workers-chromium-only
Downside is that the offscreen canvas API is only available in chromium based browsers.
Other approach you can take is by adding the canvas to the dom, let chart.js render to it, get the base64 representation and then remove the canvas directly after that like so:
let ctx = document.createElement("canvas")
document.documentElement.appendChild(ctx)
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart = new Chart(ctx, {
type: "bar",
data: {
labels: ['a', 'b', 'c', 'd', 'e', 'f', ' g'],
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
})
const base64 = chart.toBase64Image();
ctx.remove();
console.log(base64)
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
its not possible to render without attaching canvas to dom, but you can hide it and it will work as expected.
const chartEl = document.createElement("canvas");
const ctx = chartEl.getContext("2d");
chartEl.setAttribute("width", "400");
chartEl.setAttribute("height", "400");
chartEl.style.display = "none";
document.body.append(chartEl);
let chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [
{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}
]
},
options: {
scales: {}
}
});
chart.render();
console.log(chart.toBase64Image());
chartEl.remove();
I want to add a background color or a cirle with color inside doghnut chart using chartjs.
I have already added text in the center of doghnut chart.
However I am not able to add the background colour.
I also want to remove padding and margin chart.js inserts in the chart
I want a chart like this
I am able to acheive following using below code
This my code to render chart
data = {
labels: [
'performance'
],
datasets: [{
label: 'performance;,
data: [90, 10],
backgroundColor: [
'#27AE60',
'#3333331A'
]
}]
};
config = {
type: 'doughnut',
data,
options: {
cutout: 200,
legend: {
display: false,
},
plugins: {
legend: {
display: false
}
},
responsive: true,
rotation: 210, // start angle in degrees
circumference: 300,
radius: "50%"
},
plugins: [{
id: 'text',
beforeDraw: function (chart, a, b) {
let width = chart.width,
height = chart.height,
ctx = chart.ctx;
ctx.restore();
let fontSize = (height / 200).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
let text = '90%',
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
}],
centerText: {
display: true,
text: "280"
}
};
new Chart('performance', config);
You can mimic this design by using a pie chart with specific configuration options.
Here is a working example, including the posted plugin code for drawing text in the middle (note that the plugin is changed from beforeDraw to afterDraw to keep the text above the fill segment):
const data = {
datasets: [{
label: 'outer',
data: [1, 2],
backgroundColor: [
'#27AE60',
'#3333331A'
],
rotation: 210,
circumference: 300,
cutout: '50%',
borderWidth: 0
}, {
// dummy dataset to fill middle.
label: 'inner',
data: [1],
backgroundColor: '#27AE60',
weight: 3,
borderWidth: 0
}]
};
new Chart('chart', {
type: 'pie',
data: data,
options: {
borderAlign: 'inner'
},
plugins: [{
id: 'text',
afterDraw: function(chart, a, b) {
let width = chart.width,
height = chart.height,
ctx = chart.ctx;
ctx.restore();
let fontSize = (height / 200).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
let text = '90%',
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
}],
});
<div style="width:200px;height:200px"><canvas id="chart"></canvas></div>
<script src="https://cdn.jsdelivr.net/npm/chart.js#4.2.1"></script>
I am using chart.js from a frontend react application. I need to create a plot with chart.js so that I can attach it to a powerpoint slide with pptxgen. This image does not have to be rendered visually, I just need to create it when the user requests to generate the ppt.
Chart needs a context, so I created a canvas element to act as such, then tried to render and export the base64 image that I would then proceed to feed into pptxgen:
let ctx = document.createElement("canvas")
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart: Chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
} )
chart.render()
console.log(chart.toBase64Image())
But all I obtain is "data:;" which looks to be an empty image.
Do you know how to make it render?
The only way to render a chart without you specifically adding it to the dom is by making use of the offscreen-canvas as explained here in the documentation of chart.js:
https://www.chartjs.org/docs/3.7.1/general/performance.html#parallel-rendering-with-web-workers-chromium-only
Downside is that the offscreen canvas API is only available in chromium based browsers.
Other approach you can take is by adding the canvas to the dom, let chart.js render to it, get the base64 representation and then remove the canvas directly after that like so:
let ctx = document.createElement("canvas")
document.documentElement.appendChild(ctx)
ctx.setAttribute("width", "400")
ctx.setAttribute("height", "400")
let chart = new Chart(ctx, {
type: "bar",
data: {
labels: ['a', 'b', 'c', 'd', 'e', 'f', ' g'],
datasets: [{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}]
},
options: {
scales: {}
}
})
const base64 = chart.toBase64Image();
ctx.remove();
console.log(base64)
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
its not possible to render without attaching canvas to dom, but you can hide it and it will work as expected.
const chartEl = document.createElement("canvas");
const ctx = chartEl.getContext("2d");
chartEl.setAttribute("width", "400");
chartEl.setAttribute("height", "400");
chartEl.style.display = "none";
document.body.append(chartEl);
let chart = new Chart(ctx, {
type: "bar",
data: {
datasets: [
{
barPercentage: 0.5,
barThickness: 6,
maxBarThickness: 8,
minBarLength: 2,
data: [10, 20, 30, 40, 50, 60, 70]
}
]
},
options: {
scales: {}
}
});
chart.render();
console.log(chart.toBase64Image());
chartEl.remove();
I have two functions, one that gets data, and another that creates the chart. This works fine. Now I want to move the second function into a constructor, but I can't get the data to display, just an empty line chart. what am I missing?
Thanks
let data = getData() // returns arrays xs and cbrv
class BuildChart {
constructor() {
console.log(data) // <-- as expected
var ctx = document.getElementById('chart')
this.newChart = new Chart (ctx, {
type: 'line',
data: {
labels: data.xs, //
data: {
datasets: [{
labels: "cbrv",
data: data.cbrv
}],
}
}
})
}
}
function getData() {
return {
a: [{ x: 118, y: 92.82 }, {x: 115.8, y: 92.88 }, {x: 113.03, y: 93.62 } ],
b: [{ x: 218, y: 92.82 }, {x: 215.8, y: 92.88 }, {x: 213.03, y: 93.62 } ]
};
}
var data = getData();
class BuildChart {
constructor() {
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'scatter',
data: {
datasets: [
{
label: 'Example',
showLine: true,
backgroundColor: 'red',
data: data.a
},
{
label: 'Example 2',
showLine: true,
backgroundColor: 'green',
data: data.b
}
]
}
});
}
}
new BuildChart();
canvas { max-width: 400px; }
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<canvas id="myChart"></canvas>
This is the code I'm using to display the chart
<canvas id="myChart"></canvas>
<script>
var data1 = [{
x: new Date("2020-01-01 18:00:00"),
y: 1
}, {
x: new Date("2020-01-02 18:00:00"),
y: 2
},{
x: new Date("2020-01-03 18:00:00"),
y: 3
}];
var ctx = document.getElementById('myChart');
console.log(data1);
var chart = new Chart(ctx, {
type: 'line',
data: data1,
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day'
},
distribution: 'linear',
}]
}
}
});
</script>
I've tried pasting a typical chart.js example from their website and the chart is displayed just fine. I have also tried using a string in the x-axis but that doesn't seem to work as well
Can't figure out why this is happening, any help would be greatly appreciated.
As palaѕн commented, you don't correctly retrieve the 2D-Context. This should look as follows.
var ctx = document.getElementById('myChart').getContext('2d');
Further the data object needs to be defined in a different way.
data: {
datasets: [{
data: data1
}]
},
Please have a look at your amended code below.
var data1 = [{
x: new Date("2020-01-01 18:00:00"),
y: 1
}, {
x: new Date("2020-01-02 18:00:00"),
y: 2
}, {
x: new Date("2020-01-03 18:00:00"),
y: 3
}];
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
data: data1
}]
},
data1,
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day'
},
distribution: 'linear',
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="myChart" height="120"></canvas>