I'm trying to create a static (non-clickable) Pie chart using react-chartjs-2.
However I want one of the slices to "pop out", or appear bigger than the others:
Hence, I'm trying to access one of the slices in the pie chart and modify its outerRadius property.
I've encountered multiple similar questions both in Stack Overflow and in Github, which helped me come up with this:
import { Pie } from 'react-chartjs-2';
<Pie
data={data}
options={options}
getElementsAtEvent={(elems) => {
// Modify the size of the clicked slice
elems[0]['_model'].outerRadius = 100;
}}
/>
However I didn't find anything about getting a slice to pop out without the user clicking it.
After looking under Pie component's hood, I ended up finding the answer.You can find it inside componentDidMount():
import React, { Component } from 'react';
import { Pie } from 'react-chartjs-2';
class PieChart extends Component {
componentDidMount() {
const change = {
sliceIndex: 0,
newOuterRadius: 100
}
const meta = this.pie.props.data.datasets[0]._meta;
meta[Object.keys(meta)[0]]
.data[change.sliceIndex]
._model
.outerRadius = change.newOuterRadius;
}
render() {
const data = {
type: 'pie',
datasets: [ { data: [10, 20, 30] } ],
labels: ['a', 'b', 'c'],
};
const options = {};
return <Pie
ref={(self) => this.pie = self}
data={data}
options={options}
/>
}
}
export default PieChart;
I have one more solution with version 4.3.1.
Try to add offset property into datasets.
import { Pie } from 'react-chartjs-2';
<Pie
data={
datasets: [
{
data: [1, 1],
borderColor: ['black', 'transparent'],
offset: [10, 0],
},
],
}
/>
It will render Pie with 2 segments. For the first segment, you will have black border and 10px offset
Related
I am Using Charts.js Library for Displaying DoNutChart Chart.
Issue i am Facing is when i hover over the DoNutChart the label name is truncating not getting the complete width of the Labels
Js
import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { withStyles } from '#material-ui/core/styles';
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
const style = (theme) => ({
donut: {
backgroundColor: '',
'& canvas': { zIndex: 999 }
}
});
const DoNutChart = ({
chartData = [],//Array of Objects is received here from Parent Component
keyValue,//gets the key name which need to be mapped from Parent Component
styles = {},
labels = [],//getting the array of label names from Parent Component
classes
}) => {
let data = {
labels: [...labels],
datasets: [
{
data: chartData.map((x) => x[keyValue]),
backgroundColor: [
'#008712',
'#6C5AE0',
'#6FB1F7',
'#ED4E78',
'#FFEE80'
],
borderColor: ['#008712', '#6C5AE0', '#6FB1F7', '#ED4E78', '#FFEE80'],
borderWidth: 1
}
]
};
let options = {
maintainAspectRatio: true,
scales: {
y: {
beginAtZero: true,
display: false
}
},
plugins: {
legend: {
display: false
}
}
};
return (
// <div style={{ ...(styles || {}) }}>
<div className={classes.donut}>
<Doughnut data={data} height={100} options={options} />
</div>
);
};
export default withStyles(style)(DoNutChart);
I have tried using this reference
Changing the z index of tooltip in chartjs-2
by increasing the z-index still i am not getting the expected result
Attached image of truncated label Names need the full Label Names
enter image description here
I'm trying to use react-chartjs-2 in a Gatsby project. I followed this website to write down a first test to see if it works. My code is:
import React from "react"
import { Chart, Arclement, Tooltip, Legend } from 'chart.js'
import { Pie } from 'react-chartjs-2'
const data = {
labels: ['Taxation', 'Materials', 'Profit', 'Expenses', 'Wages'],
datasets: [
{
label: 'Tax bill',
data: [25, 20, 8, 12, 34],
},
],
};
const PieChart = () => {
return (
<div style={{ width: '750px' }}>
<Pie data={data} />
</div>
);
};
const Artists = (props) => {
let artistChart = getArtistChart(orderArtists(props.stats));
return (
<div id="statsCard">
<PieChart />
</div>
)
}
And I'm getting the following error:
Uncaught TypeError: Cannot read properties of undefined (reading 'prototype')
at TypedRegistry.isForType (chart.esm.js:4756:1)
at Registry._getRegistryForType (chart.esm.js:4899:1)
at eval (chart.esm.js:4879:1)
at Array.forEach (<anonymous>)
at Registry._each (chart.esm.js:4878:1)
at Registry.add (chart.esm.js:4836:1)
at Chart.value [as register] (chart.esm.js:6169:1)
at eval (webpack-internal:///./src/pages/elements/artists.jsx:17:45)
at ./src/pages/elements/artists.jsx (component---src-pages-index-js.js:62:1)
at options.factory (commons.js:3711:31)
Is it caused by a wrong way to use chartjs inside Gatsby or can it be fixed the way it is?
It looks like SSR (Server-Side Rendering) issues, so when the code is compiled in the Node server it fails.
I'd suggest importing the dependency directly into the client-side dynamically using React.Suspense or loadable components, leaving your code as:
import React from "react"
import { Chart, Arclement, Tooltip, Legend } from 'chart.js'
import loadable from '#loadable/component'
const { Pie } = loadable(() => import('react-chartjs-2'))
const data = {
labels: ['Taxation', 'Materials', 'Profit', 'Expenses', 'Wages'],
datasets: [
{
label: 'Tax bill',
data: [25, 20, 8, 12, 34],
},
],
};
const PieChart = () => {
return (
<div style={{ width: '750px' }}>
<Pie data={data} />
</div>
);
};
const Artists = (props) => {
let artistChart = getArtistChart(orderArtists(props.stats));
return (
<div id="statsCard">
<PieChart />
</div>
)
}
Or using React.Suspense:
const { Pie } = React.lazy(() => import("react-chartjs-2"));
import React from "react"
const data = {
labels: ["Taxation", "Materials", "Profit", "Expenses", "Wages"],
datasets: [
{
label: "Tax bill",
data: [25, 20, 8, 12, 34],
},
],
};
function MyComponent() {
return (
<React.Suspense fallback={"Loading"}>
<div>
<Pie data={data} />
</div>
</React.Suspense>
);
}
Note: remove the fallback if not needed
Another alternative solution is adding a null loader for the react-chartjs-2 dependency by adding the following in your gatsby-node.js:
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html" || stage === "develop-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /react-chartjs-2/,
use: loaders.null(),
},
],
},
})
}
}
Modified from: https://www.gatsbyjs.com/docs/debugging-html-builds/. In this docs you can also find more information about loadable components
In the snippet above, test is a regular expression (that's why is between slashes, /) that it should match the folder name inside node_modules of the offending module.
I want to load an image for one of the data points in a Scatter chart. The problem I have is the image doesn’t load on the initial page/chart render. Image only appears when you click/interact with the chart.
I am using react-chartjs-2, any suggestions would be appreciated.
I’ve tried the following (snippet)
import { Scatter, Chart } from "react-chartjs-2";
const chartReference = useRef();
const myImage = new Image(25, 35);
myImage.src = '/img/myimage.svg';
const chartData = {
datasets: [{
label: 'my Image',
data: [{ x: dummyData, y: 25 }],
pointStyle: myImage,
radius: 1,
pointRadius: 10,
borderWidth: 0,
type: 'line',
}],
}
return (
<Scatter
height={height}
width={width}
data={chartData}
options={options}
plugins={[Zoom]}
ref={chartReference}
redraw={true}
/>
I also through of this but where should do I place this?
chartReference.current.chartInstance.data.datasets[0].pointStyle = myImage;
chartReference.current.chartInstance.update();
If you manage to solve that I would like to ask a part 2 question that is the when you pan the chart unlike the built in data pointStyle the image goes off the y-axis. It only hide when at the charts actual width
It should work if you define the Image inside the component constructor...
constructor() {
super();
const myImage = new Image(25, 35);
myImage.src = "/img/myimage.svg";
and create the Scatter chart inside the render method.
render() {
return (
<div>
<Scatter
data={this.state.chartData }
options={this.state.chartOptions}
...
/>
</div>
);
}
Please have a look at this StackBlitz.
I am using react-vis and trying to implement a line chart with legends that can filter as shown on the first plot on top of this website: https://uber.github.io/react-vis/examples/showcases/plots
Basically when the legend item is clicked the whole series goes dim, along with the legend item.
I am guessing that I need to use onItemClick attribute in under Legends in https://uber.github.io/react-vis/documentation/api-reference/legends to change the opacity of the line, which I have successfully created
<LineSeries
data={data1}
opacity={1}
stroke="#f5222d"
strokeStyle="solid"
/>
I am not sure on how to proceed from here, building the function for onItemClick
Here is a simple example
import React from "react";
import {
XYPlot,
LineSeries,
DiscreteColorLegend
} from "react-vis";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
series: [{
title: "Apples",
disabled: false,
data: [{ x: 0, y: 12 }, { x: 1, y: 22 }]
}]
};
}
clickHandler = (item, i) => {
const { series } = this.state;
series[0].disabled = !series[0].disabled;
this.setState({ series });
};
render() {
const { series } = this.state;
return (
<div>
<DiscreteColorLegend
onItemClick={this.clickHandler}
width={180}
items={series}
/>
<XYPlot height={200} width={200}>
<LineSeries
data={series[0].data}
opacity={series[0].disabled ? 0.2 : 1}
stroke="#f5222d"
strokeStyle="solid"
/>
</XYPlot>
</div>
);
}
}
I have a doughnut chart with static labels - what is changing, is only the data with values for labels. It's all about filtering data. But I have some weird issue and I can't figure out whats going on.
For example I've got something like this:
labels with hidden option set to true
I figure out that 'undefined' value in Array, makes item hidden so in case from picture it will be for example: [234, undefined, 21, undefined, 8].
Ok it's seems to be fine but when I use filter panel to change data in my application, and props with this Array of values is changing it's not rerendering label view, for example when I change array to [234, 100, 21, undefined, 8], label at position label1 should change 'hidden' property to false - it won't happening and I don't know why.
I paste here only render method, if u need to know something else please tell me:
render() {
const chartOptions = {
legend: {
display: true,
position: 'right',
labels: {
boxWidth: 12
}
}
};
const chartData =
[{
label: 'SomeLabel',
data: this.props.chartData.values,
yAxisId: 'yAxisA',
type: 'doughnut',
backgroundColor: ['#a3e1d4', '#dedede', '#9CC3DA', '#0475ad', '#f8ac59', '#ED5565', '#23c6c8', '#c2c2c2', '#1c84c6'],
}];
const title = (<h5>{this.props.title}</h5>);
const doughnutData = {
labels: this.props.chartData.labels,
datasets: chartData
};
const clonedDoughnutData = Object.assign({}, doughnutData);
const chart = (
<CustomDoughnut
data={clonedDoughnutData}
options={chartOptions}
height={150}
/>
);
const noData = (<NoData isDataVolume={false}/>);
const waveLoader = (<WaveLoader loading={this.props.loading}/>);
return (
<div>
<Tile
loading={this.props.overlayLoading}
title={title}
content={this.props.loading ? waveLoader : this.props.chartData.values.length > 0 ? chart : noData}
dynamicElementsService={this.props.dynamicElementsService}
parentView={this.props.parentView}
element={this.props.element}
status={this.props.status}
label={this.props.title}
/>
</div>
);
}
EDIT 1:
All calculations I make in other component, then I'm dispatching them to store, and then I'm getting them from store in parent component and I'm sending values as a props to component with the chart rendering.
This is how I'm handling proper values to labels:
const SomethingValues = [];
this.somethingLabels.forEach(element => {
if (analytics.chartData.Something.Map.get(element)) {
somethingValues.push(analytics.chartData.Something.Map.get(element));
} else {
somethingValues.push(undefined);
}
}
);