How Align the Legend Items in Chart.js 2? - javascript

I just need to align the Chart Legend so it don't look too messy as the default shows, here is an example what I'm trying to achieve:
Please give some code suggestions: https://jsfiddle.net/holp/68wf75r8/
new Chart(document.getElementById("field-0"), {
type: 'pie',
data: {
labels: ["Chat", "Prospeção", "Whatsapp", "Trial", "Site", "Telefone", "E-mail", "Evento"],
datasets: [{
data: [700, 400, 200, 150, 80, 50, 20, 10],
borderWidth: 2,
hoverBorderWidth: 10,
backgroundColor: pieColors,
hoverBackgroundColor: pieColors,
hoverBorderColor: pieColors,
borderColor: pieColors
}]
},
options: {
legend: {
labels: {
padding: 20
}
}
}
});

There is legend.labels.generateLabels hook you generally can use to customise your legend labels.
I found out, that you can put something like below to adjust Chart.js calculations.
generateLabels: function (chart) {
chart.legend.afterFit = function () {
var width = this.width; // guess you can play with this value to achieve needed layout
this.lineWidths = this.lineWidths.map(function(){return width;});
};
// here goes original or customized code of your generateLabels callback
}
Weird thing that there is no actual configuration option to achieve this.

Chartjs v2 creates an overhead to handle the legends. Basically what you are looking for is to leverage the usage of generateLabels.
The key point to bare in mind is that you need to return an valid array of legend objects.
This plunker describes the solution.
Main focus on this part:
generateLabels: (chart) => {
chart.legend.afterFit = function () {
var width = this.width;
console.log(this);
this.lineWidths = this.lineWidths.map( () => this.width-12 );
this.options.labels.padding = 30;
this.options.labels.boxWidth = 15;
};
var data = chart.data;
//https://github.com/chartjs/Chart.js/blob/1ef9fbf7a65763c13fa4bdf42bf4c68da852b1db/src/controllers/controller.doughnut.js
if (data.labels.length && data.datasets.length) {
return data.labels.map((label, i) => {
var meta = chart.getDatasetMeta(0);
var ds = data.datasets[0];
var arc = meta.data[i];
var custom = arc && arc.custom || {};
var getValueAtIndexOrDefault = this.getValueAtIndexOrDefault;
var arcOpts = chart.options.elements.arc;
var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
return {
text: label,
fillStyle: fill,
strokeStyle: stroke,
lineWidth: bw,
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
// Extra data used for toggling the correct item
index: i
};
});
}
return [];
}

I tried to do as advised by the comments above. But to see that it is really difficult. It’s better and easier for me to set:
legend: {display: FALSE, ..} `, and then render the legend using html (angular, react, view .. another render template):
// part of angualr model class
public dataSets = [{
label: "New Deals",
backgroundColor: "#88B2FF",
data: [26, 15, 5],
},
{
label: "Active Deals",
backgroundColor: "#397FFF",
data: [7, 13, 22],
},
....
this.chart = new Chart(ctx, {
type: "roundedBar",
data: {
labels: this.xLabels,
datasets: this.dataSets,
},
<div style="width: 380px;height: 200px; display: inline-block;">
<canvas id="chart" aria-label="Hello ARIA World" role="img"></canvas>
</div>
<!-- This is angular template -->
<ul class="legend">
<li *ngFor="let set of dataSets">
<i [style.backgroundColor]="set.backgroundColor" class="icon"></i>
<label>
{{ set.label }}
</label>
</li>
</ul>
<style>
.legend {
display: flex;
text-align: center;
justify-content: space-between;
font-size: 10px;
line-height: 12px;
}
.icon {
width: 10px;
height: 10px;
border-radius: 50%;
display: inline-block;
}
</style>

Related

React-Chart.js : How do I increase the space between the legends and chart?

There are a couple of questions that run along the same lines as mine. However, these questions focus on simply chart.js. I have a similar problem but on react-chart.js. How do I increase the space between the legend and chart? I have used padding but it only increases the space between the legends. Not quite what I wanted. Below is my doughnut chart component.
<div className="dougnut-chart-container">
<Doughnut
className="doughnut-chart"
data={
{
labels: ["a", "b", "c", "d", "e", "f"],
datasets: [
{
label: "Title",
data: [12821, 34581, 21587, 38452, 34831, 48312],
backgroundColor: [
'rgb(61, 85, 69)',
'rgb(115, 71, 71)',
'rgb(166, 178, 174)',
'rgb(209, 191, 169)',
'rgb(66, 63, 62)',
'rgb(43, 43, 43)',
]
}
],
}
}
options={
{
plugins: {
legend: {
labels: {
color: "white",
font: {
size: 12
},
padding: 10,
},
position: "left",
title: {
display: true,
text: "Title",
color: "grey",
padding: 10
}
}
},
elements: {
arc: {
borderWidth: 0
}
},
responsive: true,
maintainAspectRatio: true,
}
}
/>
</div>
What my chart looks like:
You can write a custom plugin as showed by this answer, but instead of adding some extra space to the height you will need to add some extra spacing to the width of the legend boxes:
var options = {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
}]
},
options: {
plugins: {
legend: {
position: 'left'
},
legendDistance: {
padding: 50
}
}
},
plugins: [{
id: 'legendDistance',
beforeInit(chart, args, opts) {
// Get reference to the original fit function
const originalFit = chart.legend.fit;
// Override the fit function
chart.legend.fit = function fit() {
// Call original function and bind scope in order to use `this` correctly inside it
originalFit.bind(chart.legend)();
// Change the height as suggested in another answers
this.width += opts.padding || 0;
}
}
}]
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>
This answer suggested by #LeeLenalee works for me. But for those who are confused and wants to see this integrated in their components, here is what I did:
<div className="dougnut-chart-container">
<Doughnut
className="doughnut-chart"
data={
{
labels: ["label_1", "label_2", "label_3", "label_4", "label_5", "label_6"],
datasets: [
{
label: "Title",
data: [12821, 34581, 21587, 38452, 34831, 48312],
backgroundColor: [
'rgb(61, 85, 69)',
'rgb(115, 71, 71)',
'rgb(166, 178, 174)',
'rgb(209, 191, 169)',
'rgb(66, 63, 62)',
'rgb(43, 43, 43)',
]
}
],
}
}
options={
{
plugins: {
legend: {
labels: {
color: "white",
font: {
size: 12
},
padding: 10,
},
title: {
display: true,
text: "A Longer Title To Occupy Space",
color: "grey",
padding: {
bottom: 10
},
font: {
size: 13
}
},
position: "left"
},
// this is the id that is specified below
legendDistance: {
padding: 130 // dictates the space
}
},
elements: {
arc: {
borderWidth: 0
}
},
responsive: true,
maintainAspectRatio: true,
}
}
plugins={
[
{
id: 'legendDistance',
beforeInit(chart, args, opts) {
// Get reference to the original fit function
const originalFit = chart.legend.fit;
// Override the fit function
chart.legend.fit = function fit() {
// Call original function and bind scope in order to use `this` correctly inside it
originalFit.bind(chart.legend)();
// Specify what you want to change, whether the height or width
this.width += opts.padding || 0;
}
}
}
]
}
/>
</div>
This is the result: result
Take note: You need to reload your page to see the changes.
for react you can try this code ->
const legendMargin = {
id: "legendMargin",
beforeInit: function (chart) {
const fitValue = chart.legend.fit;
chart.legend.fit = function fit() {
fitValue.bind(chart.legend)();
return (this.height += 40);
};
}
};
then just need to pass legendMargin as a props like this way
<Bar options={options} data={data} plugins={[legendMargin]} />

Custom tooltip React ChartJs

I'm having an issue while creating a custom tooltip using react-chartjs-2 library where my chart rerenders whenever I hover the chart and change the state of the tooltip's future data. (currently tooltip doesn't exist I'm simply logging some data which Ill use later)
I referenced this question while trying to create a tooltip however they are using a class component and I use functional component but it shouldn't really change anything but anyway. I'd be really grateful of someone could provide a working example of a custom tooltip with react-chartjs-2 because I'm still not sure whether tooltip should be a separate jsx component or what is the proper way to create a custom tooltip in React. Thanks in advance
My code
const GraphTooltip = ({ data }) => {
return (
<div
style={{
padding: 20,
position: 'absolute',
border: '1px solid',
borderColor: '#fff8f9',
backgroundColor: 'rgba(53,53,53,0.81)',
borderRadius: 4,
top: data.top,
left: data.left,
}}
></div>
);
};
const LineChart = ({ values, labels }) => {
const isSSR = useIsSSR();
const [tooltipData, setTooltipData] = useState(null);
console.log(tooltipData);
const chartRef = useRef(null);
const customTooltip = useCallback(tooltipModel => {
if (tooltipModel.tooltip.opacity == 0) {
setTooltipData(null);
console.log('Hide tooltip');
return;
}
console.log(tooltipModel);
const chart = chartRef.current;
const canvas = chart.canvas;
console.log(canvas);
if (canvas) {
const position = canvas.getBoundingClientRect();
// set position of tooltip
const left = tooltipModel.tooltip.x;
console.log(position.left);
console.log(tooltipModel.tooltip);
const top = tooltipModel.tooltip.y;
tooltipData?.top != top && setTooltipData({ top: top, left: left });
}
});
const options = useMemo(() => ({
scales: {
x: {
ticks: {
beginAtZero: true,
},
grid: {
color: '#EEF5FF',
},
},
y: {
grid: {
color: '#EEF5FF',
},
},
},
plugins: {
legend: {
display: false,
position: 'right',
},
tooltip: {
enabled: false,
external: customTooltip,
},
},
}));
const data = {
labels: labels,
datasets: [
{
data: values,
fill: false,
backgroundColor: '#88B1DD',
borderColor: '#88B1DD',
pointRadius: 6,
tension: 0.5,
},
],
};
if (isSSR) return null;
return (
<>
<div className="header"></div>
<div className="relative">
<Line data={data} options={options} ref={chartRef} />
{tooltipData ? <GraphTooltip data={tooltipData} /> : <div />}
</div>
</>
);
};
Using https://www.npmjs.com/package/test-react-chartjs-2 actually fixed this. Some problems in the package itself.

How to use a Data Array within a Chart JS dataset?

I have the following JSON, that I want to insert a chart using Chart JS:
{"Results":[{"Data":"25/02/2021","Valor":18},{"Data":"24/02/2021","Valor":2993},{"Data":"23/02/2021","Valor":1936},{"Data":"22/02/2021","Valor":1844},{"Data":"21/02/2021","Valor":1114},{"Data":"20/02/2021","Valor":1060},{"Data":"19/02/2021","Valor":1134}]}
And I created a function to load this JSON into an Array:
function ShowData(jsonObj) {
var bases = jsonObj['Results'];
var Date = [];
var Val = [];
for (var i = bases.length-1; i >= 0; i--) {
Date.push([bases[i].Data]);
Val.push([bases[i].Valor]);
}
}
When I load this Array into the Chart, As below:
var chartGraph = new Chart(ctx,{
type:'line',
data:{
labels: Date,
datasets: [
{
label: "Lbl Name",
data: Val,
borderWidth: 6,
borderColor: 'rgba(77,166,253, 0.85)',
backgroundColor: 'transparent'
}
]
},
options: {
title: {
display: true,
fontSize: 20,
text: 'Chart Name'
},
legend: {
display: true,
position: 'right',
labels: {
fontColor: '#666'
}
}
}
})
No information on "datasets" appears to me, only the "label", what is the mistake I am making?
Graphic Image
Try to split series and data, something like:
function splitData(type) {
return json.Results.map(v => v[type]);
}
// your Chart.js config
data: {
labels: splitData('Date'),
datasets: [
{
// ...otherProps,
data: splitData('Valor')
}
]
}
You cant use Date as variable name since its a build in class. Also from my testing couldnt reference the vars inside the function. But the real problem with your code is that you push an array to the val array. This made it an array containing arrays. This is not supported. If you change your code to the sample below it will work
let date = [];
let val = [];
function ShowData(jsonObj) {
var bases = jsonObj['Results'];
date = [];
val = [];
for (var i = bases.length-1; i >= 0; i--) {
date.push(bases[i].Data);
val.push(bases[i].Valor);
}
}
var chartGraph = new Chart(ctx,{
type:'line',
data:{
labels: Date,
datasets: [
{
label: "Lbl Name",
data: Val,
borderWidth: 6,
borderColor: 'rgba(77,166,253, 0.85)',
backgroundColor: 'transparent'
}
]
},
options: {
title: {
display: true,
fontSize: 20,
text: 'Chart Name'
},
legend: {
display: true,
position: 'right',
labels: {
fontColor: '#666'
}
}
}
})

ChartJS - Y Axis line not drawing

I'm making a chart using ChartJS. Everything has gone smoothly, with one exception: Although the X-axis line (the line that runs horizontally along the base of the chart) is drawing, the Y-axis line (the one that runs vertically along the left) is not, even though I've applied nearly identical configurations.
I've played around with this extensively, and can't figure out what I'm doing wrong.
I'm getting near trying to do something hacky (basically, absolutely position a line on top of the chart, after trying to use the container to determine its length and location -- a bit of a nightmare), but I wanted to see if anyone here who was more familiar with ChartJS might have a sense of what I'm doing wrong.
Here's the CodePen (JS below the rest of the post).
And here's the styling documentation I was following to attempt to get it working. (See the zeroLineWidth and zeroLineColor values).
Any ideas what I'm doing wrong, or how to fix this?
// Colors
const squidInk = '#232F3E'; // Background and hover circle interior
const mermaid = '#00A4B4'; // Gridlines
const siren = '#0099D9'; // Line and points
const darkGrey = '#3A444F'; // Fill below line - NOTE: doesn't seem to be one of main colors
const white = '#FFF'; // Font white - in one place to change globally (sync w CSS)
const mobileBreakpoint = 768;
const isMobile = window.innerWidth <= mobileBreakpoint;
// Helper for below tooltip generation
const getTooltipStyles = (tooltipModel, position) => ({
opacity: 1,
position: 'absolute',
left: position.left + window.pageXOffset + tooltipModel.caretX + 'px',
top: position.top + window.pageYOffset + tooltipModel.caretY + 'px',
fontFamily: tooltipModel._bodyFontFamily,
fontSize: tooltipModel.bodyFontSize + 'px',
fontStyle: tooltipModel._bodyFontStyle,
padding: tooltipModel.yPadding + 'px ' + tooltipModel.xPadding + 'px',
pointerEvents: 'none'
});
// Chart points (y-coords; there are 20).
// Loosely approximates the data in the designs.
const points = [
4, 4, 8, 19, 22,
25, 27, 27, 28, 30,
32, 34, 40, 44, 46,
48, 52, 53, 55, 57
];
// The value of the data key in the Chart config.
// Contains points in the main (only) dataset,
// and related configuration.
const data = {
// Years from 1997 to 2016.
// Hide all but first and last label on mobile
labels: points.map((_, ind) =>
isMobile && ![0, points.length - 1].includes(ind)
? ''
: 1997 + ind
),
datasets: [{
data: points,
fill: true,
backgroundColor: darkGrey,
borderColor: siren,
borderWidth: 4,
pointHitRadius: 20,
pointRadius: isMobile ? 0 : 2,
pointHoverRadius: isMobile ? 0 : 10,
pointHoverBackgroundColor: squidInk,
pointHoverBorderWidth: 3
}]
};
// Function to replace the tooltip with custom HTML.
// NOTE: This needs to be a function, not a const, because of how
// `this` is bound.
function customTooltip (tooltipModel) {
if (isMobile) {
return '';
}
// Tooltip Element
let tooltipEl = document.getElementById('chartjs-tooltip');
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'chartjs-tooltip';
tooltipEl.innerHTML = '<div></div>';
document.body.appendChild(tooltipEl);
}
// Hide if no tooltip
if (tooltipModel.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set caret Position
tooltipEl.classList.remove('above', 'below', 'no-transform');
tooltipEl.classList.add(
tooltipModel.yAlign
? tooltipModel.yAlign
: 'no-transform'
);
// Set Text
if (tooltipModel.body) {
const titleLines = tooltipModel.title || [];
const bodyLines = tooltipModel.body.map(bodyItem => bodyItem.lines);
// Text for hover percentages
const percentExternal = bodyLines[0];
const percentSellers = 100 - percentExternal;
// These spans are styled in the CSS
const innerHtml = `
<span class="percent-tooltip external">${percentExternal}%</span>
<span class="percent-tooltip sellers">${percentSellers}%</span>
`;
const root = tooltipEl.querySelector('div');
root.innerHTML = innerHtml;
}
// `this` will be the overall tooltip
const position = this._chart.canvas.getBoundingClientRect();
// Apply positional styles to the tooltip (cleaned up and put above for clarity)
const styles = getTooltipStyles(tooltipModel, position);
Object.keys(styles).forEach(k => tooltipEl.style[k] = styles[k]);
};
// High-level chart options
const options = {
legend: {
display: false
},
tooltips: {
enabled: false,
custom: customTooltip // Custom tooltip func (above)
},
scales: {
yAxes: [{
ticks: {
// Include a percentage sign in the ticks.
// Hide zero label on mobile.
callback: value => isMobile ? (value ? `${value}%` : '') : `${value}%`,
fontColor: white,
max: 100,
stepSize: isMobile ? 50 : 25
},
scaleLabel: {
display: !isMobile,
labelString: '% OF MERCHANDISE SALES',
fontColor: white
},
gridLines: {
color: mermaid,
zeroLineColor: white,
zeroLineWidth: 2,
drawBorder: false
}
}],
xAxes: [{
gridLines: {
drawOnChartArea: false,
// The x zero-line isn't painting! Maybe because it's not at zero (but at 1997)?
// NOTE: I tried fixing this by messing with the data, so that the x-axis included 0, but that didn't work.
zeroLineColor: white,
zeroLineWidth: 2
},
ticks: {
fontColor: white
}
}]
}
};
// Find the div to insert the chart into
const ctx = document.getElementById('chart').getContext('2d');
// And generate the chart
const chart = new Chart(ctx, {
type: 'line',
data,
options,
});
not sure why option zeroLineColor works for one axis, and not the other.
but we can use an array of colors for the gridlines,
setting the first as white, and the rest as transparent.
see following working snippet...
$(document).ready(function() {
// Colors
const squidInk = '#232F3E'; // Background and hover circle interior
const mermaid = '#00A4B4'; // Gridlines
const siren = '#0099D9'; // Line and points
const darkGrey = '#3A444F'; // Fill below line - NOTE: doesn't seem to be one of main colors
const white = '#FFF'; // Font white - in one place to change globally (sync w CSS)
const transparent = 'transparent';
const mobileBreakpoint = 768;
const isMobile = window.innerWidth <= mobileBreakpoint;
// Helper for below tooltip generation
const getTooltipStyles = (tooltipModel, position) => ({
opacity: 1,
position: 'absolute',
left: position.left + window.pageXOffset + tooltipModel.caretX + 'px',
top: position.top + window.pageYOffset + tooltipModel.caretY + 'px',
fontFamily: tooltipModel._bodyFontFamily,
fontSize: tooltipModel.bodyFontSize + 'px',
fontStyle: tooltipModel._bodyFontStyle,
padding: tooltipModel.yPadding + 'px ' + tooltipModel.xPadding + 'px',
pointerEvents: 'none'
});
// Chart points (y-coords; there are 20).
// Loosely approximates the data in the designs.
const points = [
4, 4, 8, 19, 22,
25, 27, 27, 28, 30,
32, 34, 40, 44, 46,
48, 52, 53, 55, 57
];
// The value of the data key in the Chart config.
// Contains points in the main (only) dataset,
// and related configuration.
const data = {
// Years from 1997 to 2016.
// Hide all but first and last label on mobile
labels: points.map((_, ind) =>
isMobile && ![0, points.length - 1].includes(ind)
? ''
: 1997 + ind
),
datasets: [{
data: points,
fill: true,
backgroundColor: darkGrey,
borderColor: siren,
borderWidth: 4,
pointHitRadius: 20,
pointRadius: isMobile ? 0 : 2,
pointHoverRadius: isMobile ? 0 : 10,
pointHoverBackgroundColor: squidInk,
pointHoverBorderWidth: 3
}]
};
// Function to replace the tooltip with custom HTML.
// NOTE: This needs to be a function, not a const, because of how
// `this` is bound.
function customTooltip (tooltipModel) {
if (isMobile) {
return '';
}
// Tooltip Element
let tooltipEl = document.getElementById('chartjs-tooltip');
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'chartjs-tooltip';
tooltipEl.innerHTML = '<div></div>';
document.body.appendChild(tooltipEl);
}
// Hide if no tooltip
if (tooltipModel.opacity === 0) {
tooltipEl.style.opacity = 0;
return;
}
// Set caret Position
tooltipEl.classList.remove('above', 'below', 'no-transform');
tooltipEl.classList.add(
tooltipModel.yAlign
? tooltipModel.yAlign
: 'no-transform'
);
// Set Text
if (tooltipModel.body) {
const titleLines = tooltipModel.title || [];
const bodyLines = tooltipModel.body.map(bodyItem => bodyItem.lines);
// Text for hover percentages
const percentExternal = bodyLines[0];
const percentSellers = 100 - percentExternal;
// These spans are styled in the CSS
const innerHtml = `
<span class="percent-tooltip external">${percentExternal}%</span>
<span class="percent-tooltip sellers">${percentSellers}%</span>
`;
const root = tooltipEl.querySelector('div');
root.innerHTML = innerHtml;
}
// `this` will be the overall tooltip
const position = this._chart.canvas.getBoundingClientRect();
// Apply positional styles to the tooltip (cleaned up and put above for clarity)
const styles = getTooltipStyles(tooltipModel, position);
Object.keys(styles).forEach(k => tooltipEl.style[k] = styles[k]);
};
// High-level chart options
const options = {
legend: {
display: false
},
tooltips: {
enabled: false,
custom: customTooltip // Custom tooltip func (above)
},
scales: {
yAxes: [{
ticks: {
// Include a percentage sign in the ticks.
// Hide zero label on mobile.
callback: value => isMobile ? (value ? `${value}%` : '') : `${value}%`,
fontColor: white,
max: 100,
stepSize: isMobile ? 50 : 25
},
scaleLabel: {
display: !isMobile,
labelString: '% OF MERCHANDISE SALES',
fontColor: white
},
gridLines: {
color: mermaid,
zeroLineColor: white,
zeroLineWidth: 2,
drawBorder: false
}
}],
xAxes: [{
gridLines: {
color: points.map((_, ind) =>
ind === 0
? white
: transparent
),
lineWidth: 2
},
ticks: {
fontColor: white
}
}]
}
};
// Find the div to insert the chart into
const ctx = document.getElementById('chart').getContext('2d');
// And generate the chart
const chart = new Chart(ctx, {
type: 'line',
data,
options,
});
});
.container {
/* squidInk - matches JS */
background-color: #232F3E;
position: relative;
width: 100%;
}
.section-label {
color: white;
font-size: 20px;
position: absolute;
}
.section-label.upper {
left: 100px;
top: 60px;
}
.section-label.lower {
right: 60px;
bottom: 60px;
}
#chartjs-tooltip div {
position: absolute;
left: -10px;
top: -10px;
cursor: pointer;
}
#chartjs-tooltip .percent-tooltip {
font-size: 20px;
font-weight: bold;
display: block;
position: absolute;
color: white;
}
#chartjs-tooltip span.percent-tooltip.external {
top: -30px;
}
#chartjs-tooltip span.percent-tooltip.sellers {
top: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
<div class="container">
<span class="section-label upper">Internal</span>
<canvas id="chart" width="300" height="150"></canvas>
<span class="section-label lower">External</span>
</div>

ChartJS Doughnout Chart Pie Offset on Hover

I have this:
Is it possible to animate one section of this chart, a Pie, on hover to make it grow, as in offset by either giving it padding or a different height?
I think this should be possible because on their site it says " Animate everything!", but haven't had any luck yet. Tried using events but not working.
// Doughnut chart
var myDoughnutChart = new Chart(ctx, {
type: 'doughnut',
data: {
datasets: [{
data: [11, 47, 53],
backgroundColor: ['rgb(137, 207, 191)', 'rgb(140, 187, 206)', 'rgb(144, 156, 209)']
}],
labels: [
'Elementary',
'Middle School',
'High School'
],
},
options: {
cutoutPercentage: 60,
title: {
display: true,
text: 'Grade',
position: 'top',
fontFamily: 'sans-serif',
fontSize: 18,
fontColor: 'rgb(97, 98, 116)',
padding: '20'
},
layout: {
padding: {
top: 20,
}
},
legend: {
display: true,
},
onHover: stuff,
slices: {
1: {
offset: .5
}
}
}
});
function stuff(e) {
var activePoints = myDoughnutChart.getElementsAtEvent(e);
console.log(activePoints);
}
Thanks for any help.
Add this code in update function of doughnut
var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius;
if (index == doughnutIndex) {
innerRadius = innerRadius + 10;
}
And add a new function setHoverStyle
setHoverStyle: function(arc) {
doughnutIndex = arc._index;
this.update();
},
If what you are wanting is for the section to move outward on hover, that is done with simply setting hoverOffset with a number. See this example and documentation here.

Categories

Resources