Recharts Treemap Tooltip label - reactjs

When creating a TreeMap with <Tooltip/> how do i get a label in the tooltip?
I'm only getting tooltips like : 5738
In the treemap itself the names are displayed properly.
I have the same behavior when i open example from the rechart docs in codesandbox and add a tooltip.
I played around with a custom tooltip as well but could not get it working.

I had to make a custom tooltip to get this to work.
This will put the name of the cell (the root name) in the tooltip, as well.
const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="treemap-custom-tooltip">
<p>{`${payload[0].payload.root.name}`}</p>
<p>{`${payload[0].payload.name} : ${payload[0].value}`}</p>
</div>
);
}
return null;
};
<Treemap
width={400}
height={400}
aspectRatio={4 / 3}
data={formattedData}
dataKey="size"
stroke="#fff"
fill="#8884d8"
>
<Tooltip content={<CustomTooltip />}/>
</Treemap>

<Treemap
data={maxunit}
backgroundColor="rgb(137,141,141)"
dataKey="fundUnit"
nameKey="customerName"
content={<CustomizedContent />}
>
const CustomizedContent = (props) => {
const { depth, x, y, width, height, index, name } = props;
return (
<g>
<rect
x={x}
y={y}
width={width}
height={height}
style={{
fill:
depth < 2
? DEFAULT_COLORS[index % DEFAULT_COLORS.length]
: 'none',
stroke: '#fff',
strokeWidth: 2 / (depth + 1e-10),
strokeOpacity: 1 / (depth + 1e-10),
}}
/>
{depth === 1 ? (
<text
x={x + width / 2}
y={y + height / 2 + 7}
textAnchor="middle"
fill="#fff"
fontSize={14}
>
{name}
</text>
) : null}
{depth === 1 ? (
<text
x={x + 120}
y={y + 18}
fill="#fff"
fontSize={12}
fillOpacity={0.9}
>
{labels[index]}
</text>
) : null}
</g>
);
};
this code works for tree-map inside text

Related

How to show the percentage after the bar chart in react recharts?

I want to show this percentage after the bar chart. I have made this with react recharts
Check photo
<BarChart
width={window.innerWidth < 900 ? 280 : 380}
height={200}
data={data}
margin={{ top: 20, right: 30, left: 20, bottom: 5 }}
layout='vertical'
>
{/* <CartesianGrid strokeDasharray="3 3" /> */}
<XAxis type='number' tick={false} axisLine={false} />
<YAxis type='category' dataKey='name' width={window.innerWidth < 900 ? 110 : 120}
stroke="#fff" style={{ fontSize: '14px' }} />
<Bar dataKey="pv" stackId="a" fill="#4EDCF0" />
</BarChart>
You can use cutom tooltips to write your own logic to show percentage
Working example if u want to take a look - https://codesandbox.io/s/epic-cache-kx8ze2?file=/src/App.js
<BarChart
width={500}
height={300}
data={data}
margin={{
top: 5,
right: 30,
left: 20,
bottom: 5
}}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip content={<CustomTooltip />} />
<Legend />
<Bar dataKey="amt" barSize={20} fill="#8884d8" />
</BarChart>
Custom tooltip
const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p className="label">{`${label} : ${payload[0].value}`}</p>
<p> percentage : {percentage (payload)}</p>
</div>
);
}
return null;
};
the function to calculate the percentage
const percentage = (data)=>{
console.log(data[0].value);
const total = 10000
const calcualtion = (data[0].value/total) * 100 // total to be replaced by the totla value
return calcualtion
}
hope it helps

How to zoom in and zoom out on canvas using button in konvajs react

I want to make my canvas zoom in and zoom out through button onclick function
i have implemented through onwheel but unable to do it through button please help
https://codesandbox.io/s/react-canvas-n779q2?file=/src/App.js
function App() {
const stageRef = useRef(null);
const width = 500;
const height = 500;
const [stage, setStage] = useState({
scale: 1,
x: 0,
y: 0
});
const scaleRelativeToPoint = (point, increaseScale) => {
const scaleBy = 1.02;
const stage = stageRef.current;
const oldScale = stage.scaleX();
const mousePointTo = {
x: point.x / oldScale - stage.x() / oldScale,
y: point.y / oldScale - stage.y() / oldScale
};
const newScale = increaseScale ? oldScale * scaleBy : oldScale / scaleBy;
setStage({
scale: newScale,
x: (point.x / newScale - mousePointTo.x) * newScale,
y: (point.y / newScale - mousePointTo.y) * newScale
});
};
const handleWheel = (e) => {
e.evt.preventDefault();
scaleRelativeToPoint(
e.target.getStage().getPointerPosition(),
e.evt.deltaY < 0
);
};
return (
<>
<Header />
<Container fluid>
<Row>
<Col xs={9}>
<Row className="">
<Button
variant="primary"
onClick={() => {
scaleRelativeToPoint(
// zoom relative to center of the screen
{
x: width / 2,
y: height / 2
},
true
);
}}
>
+
</Button>{" "}
<Button
variant="secondary"
onClick={() => {
scaleRelativeToPoint(
// zoom relative to center of the screen
{
x: width / 2,
y: height / 2
},
false
);
}}
>
-
</Button>{" "}
</Row>
<Row className="d-grid justify-content-center canvasborder">
{/* //artboard */}
<Stage
className="mt-5 ml-5"
width={width}
height={height}
onWheel={handleWheel}
scaleX={stage.scale}
scaleY={stage.scale}
x={stage.x}
y={stage.y}
ref={stageRef}
>
<Layer>
<Rect fill="Blue" height={500} width={500} />
</Layer>
</Stage>
</Row>
</Col>
</Row>
</Container>
</>
);
}
Demo: https://codesandbox.io/s/react-canvas-forked-910kdh?file=/src/App.js:343-2909

Change <svg:path/> Opacity on MouseOver

I'm trying to create an effect where if a user mouses over a line chart the parts of the svg:path elements that are to the right of the mouse are faded out while the parts of the svg:path element to the left remain at full opacity.
I've tried a few options to no avail - see below.
My first try was to use a path with mask which does change the opacity, but the rest of the lines are hidden because they are not under the mask.
<defs>
<mask
id='mask-for-line'
maskUnits="userSpaceOnUse"
maskContentUnits="userSpaceOnUse"
>
<rect style={{opacity: .5, stroke: 'none', fill: 'white'}}
x={x}
y={y}
width={width}
height={height}
/>
</mask>
</defs>
<path mask='url(#mask-for-line)' ... />
My second try was to put an svg:rect over the faded-out section, but that doesn't work either.
<rect x={x} y={0} width={width} height={height}
style={{opacity: .1, stroke: 'none', fill: 'lightgray'}}/>
Thanks to the inspiration from michael-rovinsky I was able to solve the problem. Within the mask, I have one <rect/> at full opacity covering the left-side of the chart and a second <rect/> at 25% opacity covering the right-side of the chart.
<defs>
<mask
id='mask-for-line'
maskUnits="userSpaceOnUse"
maskContentUnits="userSpaceOnUse"
>
<rect style={{fillOpacity: .25, fill: 'white'}}
x={x}
y={y}
width={width - x}
height={height}
/>
<rect style={{fillOpacity: 1, fill: 'white'}}
width={x}
height={height}
/>
</mask>
</defs>
You can try linear gradient with variable stop offsets:
const svg = d3.select('svg');
const width = parseInt(svg.attr('width'));
const height = parseInt(svg.attr('height'));
console.log(width, height);
const colors = ['red', 'green', 'blue', 'orange', 'purple', 'brown'];
const defs = svg.append('defs');
colors.forEach(color => {
const grad = defs.append('linearGradient').attr('id', `${color}-opacity-mask`);
grad.append('stop').attr('offset', '0%').attr('stop-color', color).attr('stop-opacity', 1);
grad.append('stop').attr('stop-color', color).attr('stop-opacity', 1).classed('mid-stop', true);
grad.append('stop').attr('stop-color', color).attr('stop-opacity', 0.25).classed('mid-stop', true);
grad.append('stop').attr('offset', '100%').attr('stop-color', color).attr('stop-opacity', 0.25);
})
const step = 100;
const paths = colors.map(color => {
let path = '';
for (let index = 0; index <= width / step; index++)
if (!index)
path = `M 0,${Math.random() * height}`;
else
path += `L ${index * step},${Math.random() * height}`;
return {color, path};
});
paths.forEach(({path, color}) => svg.append('path').attr('d', path).style('stroke', `url(#${color}-opacity-mask)`).style('fill', 'none'));
const line = svg.append('line')
.attr('y1', 0)
.attr('y2', height)
.style('stroke', 'black')
.style('stroke-dasharray', '3 3')
.style('visibility', 'hidden');
svg.on('mousemove', e => {
const pct = Math.round(100 * e.layerX / width);
svg.selectAll('.mid-stop').attr('offset', `${pct}%`);
line.attr('x1', e.layerX).attr('x2', e.layerX).style('visibility', 'visible');
});
svg.on('mouseleave', e => line.style('visibility', 'hidden'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="500" height="200">
</svg>

How to move view to the top of accordion in material ui

I am using material ui accordion in my reactjs project. Here I am facing a problem when accordion opens I want to focus on the top of accordion detail content. I tried adding scrolling it to top but this does not seems to be working.
Here are my Code
<Accordion
key={i + 1}
square
expanded={expandAccordion === `panel${i + 1}`}
onChange={handleChange(`panel${i + 1}`, item.id)}
>
<AccordionSummary
classes={{
root: classes.accordionSummery,
}}
id="accSummery"
className={classes.expansionPanel}
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1d-content"
id="panel1d-header"
>
<Typography noWrap={true} className={classes.itemHarm}>
<Chip
label={item.harm}
color={item.harmColor}
style={{
backgroundColor: `${item.harm_color}`,
width: "100%",
minWidth: "100px",
color: "#ffffff",
}}
/>
<Typography style={{ flex: 1 }} />
</Typography>
</AccordionSummary>
<AccordionDetails>
<div style={{ width: "100%" }}>
{dispensingDetailLoading ? (
<div
style={{
display: "flex",
width: "100%",
justifyContent: "center",
}}
>
<CircularProgress color="primary" />
</div>
) : (
<div ref={detailRef}>
<DetailComponent data={slide1} />
<DetailComponent data={slide2} />
<DetailComponent data={slide3} />
<DetailComponent data={slide4} />
<DetailComponent data={slide5} />
<DetailComponent data={slide6} />
<DetailComponent data={slide7} />
</div>
)}
Here is on change
const handleChange = (panel, id) => (event, newExpanded) => {
setExpanded(newExpanded ? panel : false);
// passing props to parent component
handleAccordionChange(id, newExpanded, panel);
if (newExpanded === true) {
getDispensingData(id);
setSlides(0);
}
onFocusView();
};
const detailRef = useRef();
const onFocusView = () => {
const scrollHeight = window.pageYOffset - window.innerHeight;
const h = window.scrollY - detailRef.current.clientHeight;
// const h = window.scrollY - detailRef.current.offsetTop;
console.log("detailRef", detailRef);
window.scrollTo({
top: scrollHeight ,
left: 0,
behavior: "smooth",
});
};

Vertical Bar chars with different colors based on range of values in React

In react I to draw bar charts with different colors based for each bar based on value.
Like:
if value is 0-50 Then Green
51-100 Then Orange
101-200 Then Yellow
<BarChart data={data} margin={{ top: 5, right: 10, left: 0, bottom: 5 }}>
<CartesianGrid />
<XAxis dataKey="label" tick={{ angle: -45 }} interval={0}/>
{isIndex ?
<YAxis width={50} dataKey="value" domain={[0, max]} tickCount={11} type="number" /> :
<YAxis width={50} dataKey="value" domain={[0, max]} type="number" />}
<Tooltip content={<CustomTooltip stdVal={stdVal} unit={unit} barActiveTT={barActiveTT} lineActiveTT={lineActiveTT} />} />
<Bar dataKey="value" fill="#8884d8" onMouseOver={() => { this.setState({ barActiveTT: true }) }} onMouseOut={() => { this.setState({ barActiveTT: false }) }} >
{
data.map((entry, index) => {
var color="";
if(entry.value < 50)
{
color = "#00e400";
}
else if(entry.value > 50 && entry.value < 100)
{
color = "#ffff00";
}
else
{
color = "#ff7e00";
}
return <Cell fill="{color}" />;
})
}
</Bar>
</BarChart>
Please help

Resources