How to change colors in react charts - javascript

I'm making a chart and im kind of confused. ill attach a photo below
So first off, I want the title to not be undefined, how do I change the title? And I want to change the background color of the chart below the lines, heres my code
{data?.length > 0 && (
<Line
options={options}
height={"300%"}
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data,
}
]
}}
/>
)}

The legend label will be correctly displayed if you define label on your dataset, this was mentioned by WhiteHat in his comment.
In order to obtain the background color below the lines (basically an area chart), you need to add fill: true to the dataset.
To make it work, you also need to import and register Filler from chart.js.
Please take a look at this Code Sandbox and see how it works.

Here's how I added styled to my chart:
function MyChart({}) {
const { data } = useChartConfig({
height: 200,
grouping: "primary",
dataType: "ordinal",
});
const getSeriesStyle = React.useCallback((series) => {
// Based off my chart bars
const colorPalette = {
series1: "#354657",
series2: "#5597e2",
series3: "#28A96C",
series4: "#d44401",
series5: "#ffe65b",
series6: "#ffab1b",
};
return {
fill: colorPalette[series.label],
};
}, []);
return <Chart data={data} getSeriesStyle={getSeriesStyle} />;
}

Related

Is there a way to modify an individual column in a HexagonLayer?

So I created a flat HexagonLayer and have various interactions tied to the onClick prop as shown below.
My goal now is to modify the individual column that was clicked by adding an outline, changing the color for that column, or something else along those lines. I could probably come up with a brute force resolution by adding another layer beneath this one, but the documentation doesn't go into much detail on this and I wanted to see if there was possibly another route to take that would modify the existing layer.
I would also like to obtain info such as the number of points within a given column, but I would imagine that's related to the first part.
Here's what I currently have:
// Here's where I'm creating the settings for the HexagonLayer
const hexagonLayer = {
id: 'hexagon-layer',
data: props.G.cells,
pickable: true,
extruded: true,
radius: 50,
elevationScale: 0,
autoHighlight: true,
opacity: 0.3,
getPosition: d => d.COORDINATES,
// Here's the onClick interactions
onClick: (layer, $event) => {
// I can obtain some information from the layer variable here,
// but not nearly enough for what I'm trying to accomplish
switch (props.ctx.phase) {
case 'setup':
props.moves.placeUnit(layer.object.position)
break
case 'play':
// Replace with active unit functionality
const activeUnit = Object.keys(props.G.players[props.ctx.currentPlayer].pieces)[0]
props.moves.moveUnit(activeUnit, layer.index, layer.object.position)
break
default:
console.error('Unknown phase', props.ctx.phase)
}
return true
}
};
// Check some incoming data to add the ducks shown in the screenshot
// Not necessarily related to the question, but they were in the screenshot so I included it
useEffect(() => {
const tempPieces = []
props.G.players.forEach(player => {
Object.values(player.pieces).forEach(piece => {
tempPieces.push(
createScenegraphLayer(
piece.id,
UNIT_MODEL_MAP[piece.type],
piece.coordinates, 30
)
)
})
})
setPieces(tempPieces)
}, [props.G.cells, props.G.players])
// Rendering the layers
return (
<div className="Map">
<DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller={true}
debug={true}>
<ReactMapGL mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN}>
<Layer {...threeDLayer} />
</ReactMapGL>
<HexagonLayer {...hexagonLayer} />
{pieces.map(piece => (
<ScenegraphLayer key={piece.id} {...piece} coordinates={piece.data[0].coordinates} />
))}
</DeckGL>
<ToastContainer />
</div>
);
My goal now is to modify the individual column that was clicked by adding an outline, changing the color for that column, or something else along those lines.
To change the color of the clicked column you could utilize highlightColor and highlightedObjectIndex in the following way:
const App = () => {
const [highlightedObjectIndex, setHighlightedObjectIndex] = useState(-1);
const onClick = info => {
if (info.object) {
setHighlightedObjectIndex(info.object.index);
}
};
const layers = [
new HexagonLayer({
id: "hexagon-layer",
data,
pickable: true,
radius: 200,
getPosition: d => d.COORDINATES,
highlightColor: [0, 0, 255],
highlightedObjectIndex,
updateTriggers: {
highlightedObjectIndex
},
onClick
})
];
return (
<DeckGL
initialViewState={INITIAL_VIEW_STATE}
controller={true}
layers={layers}
>
</DeckGL>
);
};

How to make react-google Chart label clickable

I am working on react google-chart react-google-chart and it is working fine.
What I want to do is to add click event to the labels of horizontal axis and get the label name and do what ever I want to do
I have google a lot but haven't found a correct solution
What I have done is this
import React, { Component } from 'react'
import { Chart } from "react-google-charts";
export default class manpowerGraph extends Component {
render() {
const data=[
['Year', 'Sales'],
['jan', 20],
['feb', 100],
['march', 55],
['april', 120],
['may', 200],
['june', 220],
]
const options={
// Material design options
chart: {
title: 'Manpower',
},
}
return (
<div className="manpowerChart">
<Chart
chartType="Bar"
width="100%"
height="400px"
data={data}
options={options}
legendToggle
chartEvents={[
{
eventName: "ready",
callback: ({ chartWrapper, google }) => {
const chart = chartWrapper.getChart();
google.visualization.events.addListener(chart, "onmouseover", e => {
const { row, column } = e;
console.warn("MOUSE OVER ", { row, column });
});
google.visualization.events.addListener(chart, "onmouseout", e => {
const { row, column } = e;
console.warn("MOUSE OUT ", { row, column });
});
}
}
]}
/>
</div>
)
}
}
Working code Working code I want when user click on month label it should fire any event or console
I have found this with Javascript with Javascript
Change the chart type to ColumnChart and then add the click handler from ready handler.
<Chart
chartType="ColumnChart"
width="80%"
height="400px"
data={data}
options={options}
legendToggle
chartEvents={[
{
eventName: "ready",
callback: ({ chartWrapper, google }) => {
const chart = chartWrapper.getChart();
var handler = function(e) {
console.log(e);
var parts = e.targetID.split("#");
if (parts.indexOf("label") >= 0) {
let idx = parts[parts.indexOf("label") + 1];
idx = parseInt(idx);
alert(data[idx + 1][0]);
}
};
google.visualization.events.addListener(
chartWrapper.getChart(),
"click",
handler
);
}
}
]}
/>
https://codesandbox.io/s/react-google-charts-columnchart-with-click-handler-cqe1l
Edit
To answer additional questions:
You can do limited styling of x-axis labels by setting hAxis.textStyle in options, supported styling options can be found here https://developers.google.com/docs/api/reference/rest/v1/documents#TextStyle . However, you can not set cursor using textStyle.
You can not style svg through external css. But you can add style tag inside svg tag. Again, not all css styles work, but fortunately, cursor does work.
One crude way of adding style inside svg is to grab the svg element using document.querySelector and then add style as child. This can be done from your ready handler as svg element has been created by the time ready event is fired.
Updated code now looks like:
import React from "react";
import ReactDOM from "react-dom";
import Chart from "react-google-charts";
const data = [
["Year", "Sales"],
["2004", 1000],
["2005", 1170],
["2006", 660],
["2008", 1030],
["2009", 1000],
["2010", 1170],
["2011", 660],
["2012", 1030]
];
const options = {
title: "Company Performance",
curveType: "function",
legend: { position: "bottom" },
enableInteractivity: true,
hAxis: { textStyle: { color: "blue", underline: true } }
};
class App extends React.Component {
render() {
return (
<div className="App">
<Chart
chartType="ColumnChart"
width="80%"
height="400px"
data={data}
options={options}
legendToggle
chartEvents={[
{
eventName: "ready",
callback: ({ chartWrapper, google }) => {
let svg = document.querySelector("svg");
let styles = 'text[text-anchor="middle"] { cursor: pointer; }';
var css = document.createElement("style");
if (css.styleSheet) {
css.styleSheet.cssText = styles;
} else {
css.appendChild(document.createTextNode(styles));
}
svg.appendChild(css);
const chart = chartWrapper.getChart();
var handler = function(e) {
console.log(e);
var parts = e.targetID.split("#");
if (parts.indexOf("label") >= 0) {
let idx = parts[parts.indexOf("label") + 1];
idx = parseInt(idx);
alert(data[idx + 1][0]);
}
};
google.visualization.events.addListener(
chartWrapper.getChart(),
"click",
handler
);
}
}
]}
/>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Working sandbox: https://codesandbox.io/s/react-google-charts-columnchart-with-click-handler-k6fv2
It seems that what is available at the moment for clickable tool tips in react-google-charts is limited.
However in order to configure clickable tooltips for react requires you to set the tooltip option like this:
tooltip: { isHtml: true, trigger: "selection" }
(so that it stays shown when you click), and you have setup a select chartEvent event as follows:
chartEvents={[
{
eventName: "select",
callback: ({ chartWrapper, google }) => {
var selection = chartWrapper.getChart().setAction({
id: "alertAction",
text: "Click Me!",
action: function() {
alert("Stay away Corona Virus!!");
}
});
console.warn(selection);
}
}
]}
See my codesandbox here.
And here's some google documentation on setAction() function, just the way I coded it in my example. Addtionally, there are the getAction() and removeAction() functions that tie into chart tooltips found on that same documentation page.
Hopefully this helps you some.
For making the labels clickable, In the chartEvents which is passed as props under Charts
<Chart
chartEvents = {**chartEvents**}
rootProps={{ 'data-testid': '3' }}
/>
Use can pass this as chartEvents
const chartEvents = [
{
eventName: "select",
callback({ chartWrapper }) {
console.log("Selected ", chartWrapper.getChart().Ufa.Ei);
}
}
];
This will return the label name for for the chart on which u have clicked
working example

How to set additional options for Chart.js BarCharts using React-Chartkick

I'm trying to display a barchart using React-Chartkick and Chart.js, and I'd like to customise the colours of the bars. Currently, I'm able to set all the bars to the same colour by passing a prop like this: <BarChart colours={["#fff"]} />.
Using LineCharts in React-Chartkick, you can set colours of the lines by passing an array of colours through that prop. BarCharts only seems to accept the first colour, however. Is this a limitation of React-Chartkick, or am I doing something wrong?
I've tried passing options (as described here: https://www.chartjs.org/docs/latest/charts/bar.html#styling ) through the library prop as that is how I've customised the colours of the axes and labels, but this doesn't seem to affect the bars.
Here's my current code:
state = {
chartLibraryOptions: {
borderColor: "#e34402", // does nothing here
backgroundColor: "#e34402", // nor this
scales: {
yAxes: [
{
ticks: { fontColor: "#fff", autoSkip: false }
}
],
xAxes: [
{
ticks: { fontColor: "#fff" }
}
]
}
}
};
render() {
return (
<BarChart
data={this.state.chartData}
library={this.state.chartLibraryOptions}
colors={["#e34402", "#e3b502"]} // All bars are the first colour
/>
);
}
I'm expecting to be able to change the colours of each bar, but after all this I'm not sure if that's possible through Chartkick?
Well, I used the same node package in a project with different approach kinda work for me. Almost all the charts take the same attributes.
Basically, this attribute dataset={{ backgroundColor: ['white', 'yellow' ], }}
is all you need to colour each bar. You can either pass string or array of string to backgroundColor.
The backgroundColor in dataset takes two types of data String and Array(object). Typical examples of passing data are below.
When you set backgroundColor to a string, it applied the same colour to each bar. e.g backgroundColor: 'red'
BarChart - <BarChart dataset={{ backgroundColor: 'red', }} />
When you set backgroundColor to an array, it applied each colour in the array to each bar. e.g backgroundColor: ['red', 'yellow'], then you create a loop of colours base on the data length.
column chart - <ColumnChart dataset={{ backgroundColor: ['red', 'yellow' ], }} />
React Implementation Below:
/* eslint-disable no-plusplus */
import React from 'react';
import { ColumnChart, BarChart } from 'react-chartkick';
import { chartOne } from '../common/chartData';
import 'chart.js';
const MonthlyGrowth = () => {
const handleBgColors = () => {
const firstColor = "#A00B16", secondColor = "#FAA226";
const arrOfBgColors = [];
for (let i = 1; i <= chartOne.length; i++) {
if (i % 2 === 0) {
arrOfBgColors.push(secondColor)
} else {arrOfBgColors.push(firstColor)}
}
return arrOfBgColors;
}
return (
<div className="bukka-card uk-card-default bg-white pt-4 pb-2 mr-1 pl-3 pr-2 pl-
lg-5">
<h2 className="mt-2">4,500,000</h2>
<BarChart
dataset={{ borderWidth: 0, width: 0, backgroundColor: handleBgColors(), }}
data={chartOne}
/>
</div>
)
}
export default MonthlyGrowth;

Dynamically update Highcharts chart in react

I am using highcharts-react-official in react-redux to create a drilldown chart.
However when I click on a bar to drilldown, I also update some props which causes the component to re-render - which seems to prevent the drilldown event.
I kind of gathered from Change series data dynamically in react-highcharts without re-render of the chart that I should use shouldComponentUpdate and getChart() to prevent re-render and instead dynamically update the data.
My issue is that getChart() doesn't seem to work for the official highcharts react package. I'm getting Uncaught TypeError: this.refs.chart.getChart is not a function
Is there an alternative I'm meant to be using to get and dynamically update the chart? Or some examples that I could look at?
Just including render and shouldComponentUpdate parts here:
shouldComponentUpdate(nextProps, nextState) {
let chart = this.refs.chart.getChart();
//dynamically update data using nextProps
return false;
}
render () {
const options = {
chart: {
type: 'column',
height: 300,
events: {
drillup: (e) => {this.drilledUp(e)}
}
},
plotOptions: {
series: {
events:{
click: (e) => {this.categoryClicked(e)}
}
}
},
xAxis: {type: "category"},
yAxis: {title: {text: 'Amount Spent ($)'}},
series: [{
name: 'weekly spending',
showInLegend: false,
data: this.props.transactionChartData.series_data,
cursor: 'pointer',
events: {
click: (e)=> {this.weekSelected(e)}
}
}],
drilldown: {
series: this.props.transactionChartData.drilldown_data
}
};
return (
<HighchartsReact
highcharts={Highcharts}
options={options}
ref="chart"
/>
)
}
In highcharts-react-official v2.0.0 has been added allowChartUpdate option, which should work great in your case. By using this option you can block updating the chart with updating the component:
categoryClicked() {
this.allowChartUpdate = false;
this.setState({
...
});
}
...
<HighchartsReact
ref={"chartComponent"}
allowChartUpdate={this.allowChartUpdate}
highcharts={Highcharts}
options={...}
/>
Moreover, to get the chart instance use refs:
componentDidMount(){
const chart = this.refs.chartComponent.chart;
}
Live demo: https://codesandbox.io/s/98nl4pp5r4
// react native functional
import React, {useState, useRef,useLayoutEffect} from "react"
import HighchartsReactNative from '#highcharts/highcharts-react-native'
function chartcomponent(props){
const [options, setoptions] = useState({});
const chartRef = useRef(null);
useEffect(() => {
// create the options for your chart.
setoptions({chart:{}, yaxis:{}, xAxis:{},})// etc.
}, []);
useLayoutEffect(() => {
// new point to add, you can get new data via props, fetch, socket, etc.
var x = new Date(hr.timestamp).getTime();
var y = 10
// these are the important parts here:
var series = chartRef.current.props.options.series;
if (!Array.isArray(series)){return;}
var seriesdata = series[0].data;
seriesdata.push([x,y]);
// next line limits points in chart to 10, so new poitn replaces first point
if (seriesdata.length>10){seriesdata.splice(0,1);}
return () => {};
}, [props]);
return(
<View style={styles.charting}><HighchartsReactNative styles={{height:300, width:600}} options={options} ref={chartRef} ></HighchartsReactNative></View>
)
}

Dynamic datasets in Chart.js

I'm creating a React Component in typescript for each Chart type in chart.js. Most of it is working out fine. However, I've hit my first roadblock as I just remembered that you can have multiple datasets within a chart.
I have the following code for a Bar Chart
export class Bar extends React.Component<IBarProps, {}> {
constructor(props: IBarProps) {
super(props)
}
public render() {
const className = classNames('bar-chart', this.props.className)
const ctx = document.getElementById('bar-chart') as HTMLCanvasElement
let bar: Chart = new Chart(ctx, {
type: this.props.horizontal ? 'horizontalBar' : 'bar',
data: {
labels: this.props.labels,
datasets: [
{
label: this.props.label,
xAxisID: this.props.xAxisID,
yAxisID: this.props.yAxisID,
backgroundColor: this.props.backgroundColor,
borderColor: this.props.borderColor,
borderWidth: this.props.borderWidth
}
]
} as ChartData,
options: {
elements: { rectangle: { borderSkipped: this.props.borderSkipped } }
}
})
bar.update()
return (
<div className={className}>
<canvas
id="bar-chart"
width={this.props.width ? this.props.width : '400'}
height={this.props.height ? this.props.height : '400'}
/>
</div>
)
}
// private push() {
// const dataSets = this.props.dataSets
// dataSets.forEach(dataSet => {new Object(label: this.props.label,)})
// return dataSets
// }
}
The issue is that the way I've set it up, it'd only support a single dataset. What i need is that for each dataset that is defined, create an object for it and push it into the datasets array. However I'm not a Javascript expert nor typescript expert.
Would anyone be able to show me how to setup the dynamic datasets array? If you need more info see the Bar Chart Docs

Categories