How to create Histogram with grouped data in Victory (ReactJS)? - reactjs

I'm trying to create a histogram with Value, Id and Group code. I need to group the Ids based on the group code and put the labels on top. I'm also trying to add a horizontal scroll bar. Can you help me with this?
I tried to do like in this picture but I couldn't.
My data is in the form of this object
{
id: 1,
value: 0.16882,
group_id: 'group_1',
fill: 'red',
}
const App = () => {
const sharedAxisStyles = {
tickLabels: {
fontSize: 10
},
axisLabel: {
padding: 39,
fontSize: 12,
},
grid: {
stroke: "#546E7A",
strokeWidth: 0.1,
}
};
return (
<VictoryChart
domainPadding={{
x: 20,
}}
containerComponent={(
<VictoryZoomContainer
allowZoom={false}
zoomDomain={{
x: [0, 22],
}}
/>
)}
>
<VictoryLabel
x={225}
y={30}
textAnchor="middle"
text="Group code"
/>
<VictoryBar
data={data}
x={(x) => `id_${x.id}`}
y="value"
barWidth={15.8}
style={{
data: {
fill: ({datum}) => datum.fill,
}
}}
/>
<VictoryAxis
tickCount={22}
tickLabelComponent={<VictoryLabel
angle={-90}
textAnchor="end"
style={[
{ fontSize: 3, fontWeight: 'bold', fill: '#78909C' },
]}
/>}
/>
<VictoryAxis
dependentAxis
label="Value"
tickFormat={(t) => {
return (
(t).toFixed(2)
);
}}
style={sharedAxisStyles}
/>
</VictoryChart>
);
};
When I write these codes, the output I get is like this:

you will need to use VictoryGroup : https://formidable.com/open-source/victory/docs/victory-group/
And use labels to add title for each group https://formidable.com/open-source/victory/docs/victory-group/#labels

Related

Displaying in the tooltip each value along the y axis on hover

Recently started using Recharts for charting.
Here is the data that comes from the server. They need to display Barchart.
[
{
"channel_number": 1,
"data": [
{
"date": 100000,
"consumption": 1231
},
{
"date": 200000,
"consumption": 1234
},
{
"date": 300000,
"consumption": 1234
}
]
},
{
"channel_number": 2,
"data": [
{
"date": 100000,
"consumption": 800
},
{
"date": 200000,
"consumption": 823
},
{
"date": 300000,
"consumption": 1233
}
]
}
]
I need to display each consumption value on the y-axis. That is, so that when hovering over with the mouse, it shows each value. Like this for example
I get a tooltip where only the total value of consumption is displayed
My code:
<ResponsiveContainer width="100%" height={385}>
<BarChart height={300} data={newBar}>
<CartesianGrid vertical={false} />
<XAxis
height={32}
dataKey="date"
allowDuplicatedCategory={false}
tickFormatter={(tick) => convertTimestampToDate(tick, 'dd.MM')}
angle={90}
tick={{ fontSize: '12px', color: '#626C77' }}
textAnchor="start"
/>
<YAxis tick={{ fontSize: '12px', color: '#626C77' }} />
<Tooltip cursor={false} labelFormatter={() => ''} />
<Legend
align="right"
verticalAlign="top"
iconSize={6}
formatter={(value, entry, index) => (
<span style={{ color: '#969FA8' }}>{value}</span>
)}
wrapperStyle={{ fontSize: '12px', top: -51 }}
payload={data?.channel_consumption.map((item: any, index: any) => ({
id: item.channel_number,
value: `${item.id_channel}`,
color: PIE_COLORS[index],
}))}
/>
{newBar.map((el: any, index: any) => (
<Bar
dataKey="consumption"
data={el.data}
key={el.channel_number}
fill={PIE_COLORS[index]}
barSize={8}
radius={71.5}
></Bar>
))}
</BarChart>
</ResponsiveContainer>
Does anyone have any ideas? How to display each value when hovering over a bar? Probably do something with the coordinates, I can't figure it out

React Victory Chart: VictoryTooltip is not working

I am working on a React JS project. My application needs to display data in chart format. I am using Victory Chart. I can display the chart.
What I am trying to do now is that when the user hovers the mouse cursor on a bar of the bar chart, it should display a tooltip using VictoryTooltip component. But it is not working.
Here is my code:
<VictoryChart
responsive={true}
width={byMonthChartWidth}
height={byMonthChartHeight}
padding={byMonthChartPadding}
domainPadding={byMonthChartDomainPadding}
>
<VictoryAxis
style={{
axis: {
stroke: "transparent"
},
tickLabels: {
fill: props.color,
fontSize: 8,
fontWeight: "bold"
}
}}
fixLabelOverlap={true}
tickValues={[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]}
tickFormat={['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']}
preserveAspectRatio={"none"}
/>
<VictoryAxis
style={{
axis: {
stroke: "transparent"
},
tickLabels: {
fill: props.color,
fontSize: 8,
fontFamily: "roboto",
fontWeight: "bold"
}
}}
fixLabelOverlap={true}
dependentAxis
tickValues={yAxisTicks}
tickFormat={(x) => (`${x}`)}
preserveAspectRatio={"none"}
/>
<VictoryBar
labelComponent={
<VictoryTooltip
center={{ x: 225, y: 30 }}
pointerOrientation="bottom"
flyoutWidth={150}
flyoutHeight={50}
pointerWidth={150}
cornerRadius={0}
/>
}
animate={byMonthChartBarAnimation}
barWidth={byMonthChartBarWidth}
cornerRadius={{
topLeft: (data) => 5,
topRight: (data) => 5,
bottomLeft: (data) => 5,
bottomRight: (data) => 5
}}
style={{
data: {
fill: props.color,
stroke: props.color,
fontFamily: "roboto",
fillOpacity: 1,
strokeWidth: 1
}
}}
data={data}
x="identifier"
y="value"
/>
</VictoryChart>
As you can see I am trying to display a tooltip using labelComponent prop of VictoryBar component. When I hover the mouse cursor over the bar, it is not showing any tooltips. What is wrong with my code and how can I fix it?
The data variable used inside your data={data} must carry a label property which contains tooltip's contents.
You can modify tooltip's font color by adding labels object into <VictoryBar>'s style property - example below
LIVE DEMO
Example:
<VictoryBar
barRatio={1}
cornerRadius={0}
style={{ data: { fill: "#6DB65B" }, labels: { fill: "red" } }}
alignment="middle"
labels={(d) => d.y}
labelComponent={
<VictoryTooltip
center={{ x: 225, y: 30 }}
pointerOrientation="bottom"
flyoutWidth={150}
flyoutHeight={50}
pointerWidth={150}
cornerRadius={0}
flyoutStyle={{
stroke: "blue", // border-color
fill: "yellow", // background-color
}}
/>
}
data={[
{ x: "Year 1", y: 150000, label: "My label 1" },
{ x: "Year 2", y: 250000, label: "My label 1" },
{ x: "Year 3", y: 500020, label: "My label 1" },
{ x: "Year 4", y: 750000, label: "My label 1" },
{ x: "Year 5", y: 1000000, label: "My label 1" }
]}
/>

Positioning icon in SVG in React Native

Background:
I am trying to add a tooltip to a react-native-svg chart following this tutorial.
The link to the tutorial: Link
Current Code Implementation:
import React, {useState} from 'react';
import {View, Text, Dimensions} from 'react-native';
import {LineChart} from 'react-native-chart-kit';
import {Rect, Text as TextSVG, Svg} from 'react-native-svg';
const Charts = () => {
let [tooltipPos, setTooltipPos] = useState({
x: 0,
y: 0,
visible: false,
value: 0,
});
return (
<View>
<LineChart
data={{
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [
{
data: [100, 110, 90, 130, 80, 103],
},
],
}}
width={Dimensions.get('window').width}
height={250}
yAxisLabel="$"
yAxisSuffix="k"
yAxisInterval={1}
chartConfig={{
backgroundColor: 'white',
backgroundGradientFrom: '#fbfbfb',
backgroundGradientTo: '#fbfbfb',
decimalPlaces: 2,
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
style: {
borderRadius: 0,
},
propsForDots: {
r: '6',
strokeWidth: '0',
stroke: '#fbfbfb',
},
}}
bezier
style={{
marginVertical: 8,
borderRadius: 6,
}}
decorator={() => {
return tooltipPos.visible ? (
<View>
<Svg>
<Rect
x={tooltipPos.x - 15}
y={tooltipPos.y + 10}
width="40"
height="30"
fill="black"
/>
<MaterialCommunityIcons
name="run"
size={32}
color="rgb(67, 67, 67)"
/>
<TextSVG
x={tooltipPos.x + 5}
y={tooltipPos.y + 30}
fill="white"
fontSize="16"
fontWeight="bold"
textAnchor="middle">
{tooltipPos.value}
</TextSVG>
</Svg>
</View>
) : null;
}}
onDataPointClick={(data) => {
let isSamePoint = tooltipPos.x === data.x && tooltipPos.y === data.y;
isSamePoint
? setTooltipPos((previousState) => {
return {
...previousState,
value: data.value,
visible: !previousState.visible,
};
})
: setTooltipPos({
x: data.x,
value: data.value,
y: data.y,
visible: true,
});
}}
/>
</View>
);
};
Question:
I want to add the icon(Running icon) as seen on the image above, to be next to the tool-tip text.
The Icon, then the text inside the rectangle filled in Black. When I try to position it,, it shows up on the extreme top left for some reason. How do I position it?
You can use the ForeignObject component from react-native-svg and change your decorator to something like this:
decorator={() => {
return tooltipPos.visible ? (
<ForeignObject x={tooltipPos.x} y={tooltipPos.y}>
<View
style={{
width: 70,
flexDirection: 'row',
backgroundColor: 'black',
}}>
<MaterialCommunityIcons
name="run"
size={32}
color="rgb(67, 67, 67)"
/>
<Text
style={{
color: 'white',
fontSize: 16,
fontWeight: 'bold',
textAnchor: 'middle',
}}>
{tooltipPos.value}
</Text>
</View>
</ForeignObject>
) : null;
}}
The problem with what you had before is that the react-native-svg Text and Rect components use x and y coordinates and your icon doesn't, so the positioning will be off.
The benefit of the approach shown above is that you only have to specify the x and y props of the ForeignObject. Everything inside the ForeignObject can be regular views, positioned as you normally would (https://github.com/react-native-community/react-native-svg#foreignobject).
I've chosen the tooltipPos.x and tooltipPos.y for the x and y prop values of the ForeignObject respectively, but you could add an offset if necessary.
Be sure to import ForeignObject from react-native-svg.

Recharts - bar chart dynamic label position

How can I have dynamic label positions of Bars like is showing in the picture?
Here is my code till now
const data = [
{ currency: 'CHF', amount: 3, amountLabel: 3023.00 },
{ currency: 'GBP', amount: 6, amountLabel: 6275.00 },
{ currency: 'USD', amount: 10, amountLabel: 9999.00 },
{ currency: 'EUR', amount: 14, amountLabel: 14819.00 },
{ currency: 'LEK', amount: 24, amountLabel: 24023000.00 },
];
<BarChart
width={430}
height={170}
data={data}
layout="vertical">
<XAxis type="number" orientation="top" stroke="#285A64" />
<YAxis type="category" dataKey="currency" axisLine={false} dx={-5} tickLine={false}
style={{ fill: "#285A64" }} />
<Bar background dataKey="amount" fill="#285A64" barSize={{ height: 26 }}>
<LabelList dataKey="amountLabel" position="insideRight" style={{ fill: "white" }} />
</Bar>
</BarChart>
Find Sample code here jsfiddle
You should implement a React component to be injected into the prop content (LabelList)
For example (JSFiddle):
const {BarChart, Bar, XAxis, YAxis, LabelList} = Recharts;
const data = [
{ currency: 'CHF', amount: 3, amountLabel: 3023.00 },
{ currency: 'GBP', amount: 6, amountLabel: 6275.00 },
{ currency: 'USD', amount: 10, amountLabel: 9999.00 },
{ currency: 'EUR', amount: 14, amountLabel: 14819.00 },
{ currency: 'LEK', amount: 26, amountLabel: 26023000.00 },
];
const renderCustomizedLabel = (props) => {
const {
x, y, width, height, value,
} = props;
const fireOffset = value.toString().length < 5;
const offset = fireOffset ? -40 : 5;
return (
<text x={x + width -offset} y={y + height - 5} fill={fireOffset ? "#285A64" :"#fff"} textAnchor="end">
{value}
</text>
);
};
const VerticalBarChart = React.createClass({
render () {
return (
<BarChart
width={400}
height={170}
data={data}
layout="vertical">
<XAxis type="number" orientation="top" stroke="#285A64"/>
<YAxis type="category" dataKey="currency" axisLine={false} dx={-10} tickLine={false} style={{ fill: "#285A64" }} />
<Bar background dataKey="amount" fill="#285A64" barSize={{ height: 26 }}>
<LabelList dataKey="amountLabel" content={renderCustomizedLabel} position="insideRight" style={{ fill: "white" }} />
</Bar>
</BarChart>
);
}
})
ReactDOM.render(
<VerticalBarChart />,
document.getElementById('container')
);

Nivo bar graph - add a shared y axis?

I'm using nivo responsive-bar to put a plot in my app. I've been asked to add a line showing the cumulative total on the same graph. Is there any way to do this? From the documentation I'm struggling to work out how to do it.
Here's the code I have so far (I've obfuscated the axis label and function names for security reasons!)
class CChart extends React.Component {
render = () => {
return (
<div style={{ height: '40em' }}>
<h3 className='text-center'>C</h3>
<ResponsiveBar
margin={{ top: 20, right: 0, bottom: 60, left: 80 }}
data={this.props.results}
indexBy='year'
colorBy={() => '#1f77b4'}
keys={['C']}
enableLabel={false}
axisLeft={{
legend: 'C(millions)',
legendPosition: 'center',
legendOffset: -60,
tickSize: 5,
tickPadding: 15,
format: v => Math.floor(v / 1000000).toLocaleString()
}}
axisBottom={{
legend: 'Year',
legendPosition: 'center',
legendOffset: 50,
tickSize: 5,
tickPadding: 15,
tickValues: this.props.results.map(x => x.year).filter(x => x % 5 === 0)
}}
theme={{
axis: {
fontSize: '1em',
legendFontSize: '1.2em'
}
}}
tooltipFormat={value => value.toLocaleString()}
animate={false}
markers={[
{ axis: 'y', value: 0 }
]}
/>
</div>
)
}
static propTypes = {
results: PropTypes.arrayOf(PropTypes.shape({
year: PropTypes.string.isRequired,
C: PropTypes.number.isRequired
})).isRequired
}
static mapStateToProps = state => ({
results: getCResults(state)
})
}
According to the #plouc (the founder of the Nivo library), as of September, 2018 you should be able to compose graphs.
https://github.com/plouc/nivo/issues/139
(scroll down until Sept 12)
It is not possible currently (https://github.com/plouc/nivo/issues/139)

Resources