Recharts: Floating Bar Chart when another Bar has a stackId? - recharts

I want the first three values to be stacked on the first column.
I tried following Creating ranged bar chart using recharts but having a custom shape didn't solve the problem.
The closest I could get is this configuration
<Bar dataKey="value1" stackId="a" fill="#8884d8" />
<Bar dataKey="value2" stackId="a" fill="#222" />
<Bar dataKey="value3" stackId="a" fill="goldenrod" />
<Bar dataKey="value4" fill="#58a0df" />
<Bar dataKey="value5" fill="salmon" />
<Bar dataKey="total" stackId="a" fill="#8908a7" />
Setting the stackId to be the same for all Bars makes it look like this

#piaseckimaks replied on my GitHub issue
A workaround was to create an invisible bar under the other bar.
<Bar dataKey="value4" stackId="a" fill="transparent" legendType="none" />
const data = [
{
name: "Column 1",
value1: 3,
value2: 2,
value3: 1
},
{
name: "Column 2",
invisible: 6,
value4: 4
},
{
name: "Column 3",
invisible: 10,
value5: 1
},
{
name: "Total",
total: 11
}
];
https://codesandbox.io/s/stacked-bar-chart-forked-jeuv0?file=/src/App.tsx:332-351
https://github.com/recharts/recharts/issues/2524

Related

export 'Sparkles' (imported as 'Sparkles') was not found in '#react-three/drei'

Anyone knows if Sparkles particle has been removed or not in react-three/drei ? Didn't find anything in migration report of the package. It's giving error while importing.
I used the component like this:
<Canvas style={{ height: '100vh' }} >
<Environment>
<Stars radius={300} depth={60} count={5000} factor={20} saturation={1} fade />
<Cloud
opacity={0.1}
speed={0.1} // Rotation speed
width={20} // Width of the full cloud
depth={2} // Z-dir depth
segments={20} // Number of particles
/>
<pointLight position={[5, 5, 5]} intensity={.3} />
<ambientLight intensity={.3} />
<Box position={[0, 0, 0]} />
<OrbitControls autoRotate autoRotateSpeed={.5} ref={orbitRef} onChange={() => onOrbitChange() } />
</Environment>
</Canvas>
and the box component is:
<mesh
{...props}
ref={mesh}
// scale={active ? 1.5 : 1}
// onClick={(event) => setFlag(true) }
// onPointerOver={(event) => setHover(true)}
// onPointerOut={(event) => setHover(false)}
>
<boxBufferGeometry attach="geometry" args={[3, 3, 3 ]} />
<Sparkles count speed opacity color size scale noise />
</mesh>
I want to use Sparkles in Boxbuffergeometry.

Recharts - Tooltip for each Bar in a Bar Chart composed of three bars

I have in my bar chart three different bars.
I would like to have a tooltip for each bar in the bar chart and not just one for the three.
import React from 'react';
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
} from 'Recharts';
const data = [
{ name: 'Page A', uv: 4000, pv: 1982, amt: 2400 },
{ name: 'Page B', uv: 3000, pv: 1398, amt: 4739 },
{ name: 'Page C', uv: 2000, pv: 9800, amt: 9056 },
{ name: 'Page D', uv: 2780, pv: 3908, amt: 2000 },
{ name: 'Page E', uv: 1890, pv: 4678, amt: 2181 },
{ name: 'Page F', uv: 2390, pv: 3800, amt: 2873 },
{ name: 'Page G', uv: 3490, pv: 1987, amt: 2100 },
];
class SimpleBarChart extends React.Component {
render() {
return (
<BarChart
width={600}
height={300}
data={data}
margin={{ top: 5, right: 30, left: 20, bottom: 5 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<Bar dataKey="pv" barSize={20} fill="#8884d8" />
<Bar dataKey="amt" barSize={20} fill="#82ca9d" />
<Bar dataKey="uv" barSize={20} fill="#ffc658" />
</BarChart>
);
}
}
export default SimpleBarChart;
Following Natasha's answer, first create a custom tooltip:
<Tooltip content={<CustomTooltip/>} />
Add a function/component to render the custom contents. The variable tooltip is used to identify which Bar is being hovered over. The contents can be customized using the payload which contains all the bars in the selection.
var tooltip
const CustomTooltip = ({ active, payload }) => {
if (!active || !tooltip) return null
for (const bar of payload)
if (bar.dataKey === tooltip)
return <div>{ bar.name }<br/>{ bar.value.toFixed(2) }</div>
return null
}
Finally, add name and onMouseOver props to each <Bar> element:
<Bar dataKey="pv" barSize={20} fill="#8884d8"
name="Name" onMouseOver={ () => tooltip="pv" } />
When the mouse hovers over that <Bar> it will set the tooltip variable to the value "pv". Then the CustomTooltip will find that entry in the payload parameter and display the name and value.
You can create a custom tooltip like in the example here:
http://recharts.org/en-US/examples/CustomContentOfTooltip <---- Customized tooltip example (from recharts documentation)
After you create a customized tooltip, you can call it in the Bar component's OnMouseOver property which is in the documentation here:
http://recharts.org/en-US/api/Bar#onMouseOver <---- OnMouseOver
You could also use OnMouseEnter and OnMouseLeave but I know that doesn't work for everyone.
You might want to create a function that shows the tooltip when the mouse hovers over a bar and hides the tooltip when the mouse stops hovering over the bar.
You can add shared={false} props into Tooltip like this:
<Tooltip shared={false} />

defaultValue in AOR-dependent-input

I want to set defaultValue for field in aor-dependent-input,
I already set defaultValue for ReferenceInput, but how can I set defaultValue for DependentInput using SubGenreInput
Here is my code:
<Create {...propsEdit} title=" " actions="">
<SimpleForm redirect={"/caregiver/" + cid}>
{/*<ReferenceArrayInput>*/}
<DisabledInput source="user" defaultValue={cid} label="Caregiver ID"/>
<ReferenceInput label="Centre" source="centre" defaultValue={this.props.record.student.centre.id} reference="centre" sort={{ field: 'name', order: 'ASC' }} allowEmpty>
<SelectInput optionText="name" />
</ReferenceInput>
<DependentInput dependsOn="centre">
<SubGenreInput source="current_group" optionText="label" optionValue="id" type="classgroup"/>
</DependentInput>
<DependentInput dependsOn="current_group" defaultValue={this.props.record.student.id}>
<SubGenreInput source="student_id" optionText="fullname" optionValue="id" type="student"/>
</DependentInput>
{/*</ReferenceArrayInput>*/}
<RadioButtonGroupInput source="account_type" defaultValue={10} choices={[
{ id: 10, name: 'Caregiver' },
{ id: 20, name: 'Guardian' },
]} optionText="name" optionValue="id" />
<TextInput source="relationship" label="Relationship"/>
</SimpleForm>
Interface:
https://i.stack.imgur.com/wFHKC.png
// I'm not allow to post the images :(
This is a known issue which will be addressed by version 1.3.0 of admin-on-rest. In the mean time you can use this workaround:
<DependentInput source="appointmentTimeslot" dependsOn="planned" defaultValue={1}>
<ReferenceInput source="appointmentTimeslot" reference="timeslots" allowEmpty={true} >
<SelectInput optionText="name" optionValue="id" />
</ReferenceInput>
</DependentInput>
Note that we specified source on both the DependentInput component and its child. The defaultValue, however, is specified on the DependentInput component only.
This workaround won't work if you pass multiple children to the DependentInput component.

Custom legend labels in my rechart chart

I have a pretty straight forward data array for my recharts component :
{name: '12.1.2011', series1: 4000, series2: 2400, series3: 2400},
{name: '12.2.2011', series1: 3000, series2: 1398, series3: 2210},
{name: '12.3.2011', series1: 2000, series2: 9800, series3: 2290}
I would like to have labels for the series values in my Legend. Instead of the chart showing me the different colors for "series1", "series2", and "series3".
Of course I could set the actual values I want to use for my legend in the JSON already but this just doesn't look right. Eg :
{name: '12.1.2011', 'My nice long descriptive text': 4000, 'Some other text': 2400, 'Some other descriptive text': 2400},
{name: '12.2.2011', 'My nice long descriptive text': 3000, 'Some other text': 1398, 'Some other descriptive text: 2210},
{name: '12.3.2011', 'My nice long descriptive text': 2000, 'Some other text': 9800, 'Some other descriptive text: 2290}
I need to map my series level to a descriptive label.
I have looked at content in Legend : http://recharts.org/#/en-US/api/Legend, but that seems more concerned with completely rewriting the Legend Component.
In your Line, Bar and Area add a name attribute.
Example:
<Line name="# Apples" type="monotone" dataKey="series1" stroke="#FF0000" />
<Line name="# Bananas" type="monotone" dataKey="series2" stroke="#FFFF00" />
<Line name="# Grapes" type="monotone" dataKey="series3" stroke="#FF00FF" />
The legend will pick this up automatically:
http://recharts.org/en-US/api/Legend
By default, the content of legend is generated by the name of Line,
Bar, Area, etc. When no name has been setted, dataKey will be used to
generate legend content alternatively.
If you're looking to get this working on a <Pie /> you can override the <Legend /> payload. Please see the following example;
<Legend
payload={
data.map(
(item, index) => ({
id: item.name,
type: "square",
value: `${item.name} (${item.value}%)`,
color: colors[index % colors.length]
})
)
}
/>
http://recharts.org/en-US/api/Legend#payload
For custom legend, use content props, Ref: https://recharts.org/en-US/api/Legend#content
const renderLegend = (props) => {
const { payload } = props;
return (
<ul>
{
payload.map((entry, index) => (
<li key={`item-${index}`}>{entry.value}</li>
))
}
</ul>
);
}
<Legend content={renderLegend} />

JQPlot replot. Updating PointLabels

I have a bar chart and I need to update its data, also a PointLabels. Data is updating, but PointLabels are the same, from previous plot. How to update a PointLabels?
// here are labels.
var my_labels = [["2 g. <br /> 47$"],["2 g. <br /> 48$"],["7 g. <br /> 49$"],[],["10 g. <br /> 51$"],["6 g. <br /> 52$"],["4 g. <br /> 53$"]];
$.jqplot.config.enablePlugins = true;
var s1 = [2, 6, 7, '' , 10, 6, 4];
var ticks = [47,48, 49, 50, 51, 52, 53];
// initializing plot
plot1 = $.jqplot('chart1', [s1], {
// Only animate if we're not using excanvas (not in IE 7 or IE 8)..
canvasOverlay: {
show: true,
objects: [
{verticalLine: {
name: 'barney',
x: 4,
lineWidth: 2,
color: 'gray',
shadow: false
}}
]
},
animate: !$.jqplot.use_excanvas,
seriesDefaults:{
renderer:$.jqplot.BarRenderer,
// setting labels to my own defined labels
pointLabels: { show: true, labels : my_labels, escapeHTML: false },
color: '#E6D49F'
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: ticks,
max: 100
}
},
highlighter: { show: false },
});
$('#chart1').bind('jqplotDataClick',
function (ev, seriesIndex, pointIndex, data) {
$('#info1').html('series: '+seriesIndex+', point: '+pointIndex+', data: '+data);
}
);
});
// reploting function call
setInterval(function(){replot()},4000);
var a = 1;
var labels;
// reploting function
function replot()
{
var data;
switch(a)
{
case 1:
data = [[1,4], [2,6], [3, 8],[4,0],[5, 9],[6, 7],[7, 3]];
labels = [["4 g. <br /> 47$"],["6 g. <br /> 48$"],["8 g. <br /> 49$"],[],["9 g. <br /> 51$"],["7 g. <br /> 52$"],["3 g. <br /> 53$"]];
break;
case 2:
data = [[1,3], [2,7], [3, 7],[4,0],[5, 8],[6, 6],[7, 4]];
labels = [["3 g. <br /> 47$"],["6 g. <br /> 48$"],["8 g. <br /> 49$"],[],["9 g. <br /> 51$"],["7 g. <br /> 52$"],["3 g. <br /> 53$"]];
break;
case 3:
data = [[1,5], [2,5], [3, 9],[4,0],[5, 10],[6, 8],[7, 2]];
labels = [["5 g. <br /> 47$"],["6 g. <br /> 48$"],["8 g. <br /> 49$"],[],["9 g. <br /> 51$"],["7 g. <br /> 52$"],["3 g. <br /> 53$"]];
break;
}
//updating data
plot1.series[0].data = data;
//trying to update pointlabels
plot1.series[0].pointLabels.labels = labels;
plot1.replot();
if(a == 3)
a = 0;
a++;
}
I had the same problem and thought that I am doing something wrong. But now seeing someone else with the same problem, it seems that the problem is with the plugin itself.
I found a workaround to this problem from one of the comments on my own post.
After replot try directly updating the divs containig the point labels like this.
for(i=0;i<labels.length;i++){
$("#chart1").find('.jqplot-series-0.jqplot-point-'+i).html(''+labels[i]);
}
I hope someone will provide a better solutions someday instead of this workaround.
I appreciate this is an old thread but I have just experienced the same issue and added the following as the first line in the "$.jqplot.PointLabels.draw" function, which removes all previously added labels prior to re-drawing them:
$('.jqplot-point-label',plot.target).remove();
Ran into a similar problem and found this answer. Updating plot1.series[0].plugins.pointLabels.labels instead of plot1.series[0].pointLabels.labels did the trick for me.

Resources