Last active
October 10, 2024 23:55
-
-
Save kidroca/19e5fe2de8e24aa92a41e94f2d41eda4 to your computer and use it in GitHub Desktop.
Render recharts svg chart inside a PDF document created with react-pdf/renderer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react'; | |
import { Global } from 'recharts'; | |
import { htmlSvgToPdfSvg } from '../imageFromSvg'; | |
export const ChartSvg = ({ debug, style, children, width, height }) => { | |
return chartToPdfSvg(children, width, height, debug, style); | |
}; | |
const chartToPdfSvg = (children, width, height, debug, style) => { | |
Global.set('isSsr', true); | |
const component = htmlSvgToPdfSvg(children); | |
Global.set('isSsr', false); | |
const result = React.cloneElement(component, { width, height, debug, style }); | |
return result; | |
}; | |
export default ChartSvg; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { View } from '@react-pdf/renderer'; | |
import { CartesianGrid, Label, Scatter, ScatterChart, XAxis, YAxis } from 'recharts'; | |
import Chart from './Chart'; | |
export const ExampleUsage = ({ data = getSampleData() }) => ( | |
<View> | |
<Chart width={600} height={300}> | |
<MyRechartsChart data={data} /> | |
</Chart> | |
</View> | |
); | |
const MyRechartsChart = ({ width, height, data }) => ( | |
<ScatterChart width={width} height={height}> | |
<CartesianGrid /> | |
<XAxis name="x" dataKey="x" /> | |
<YAxis name="y" dataKey="y" /> | |
<Scatter name="My Scatter" data={data} isAnimationActive={false} /> | |
</ScatterChart> | |
) | |
function getSampleData() { | |
return [ | |
{ x: 100, y: 100 }, | |
{ x: 200, y: 100 }, | |
{ x: 200, y: 150 }, | |
{ x: 150, y: 200 }, | |
{ x: 125, y: 150 } | |
] | |
} | |
export default ExampleUsage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { createElement } from 'react'; | |
import ReactDom from 'react-dom/server'; | |
import reactHtmlParser from 'react-html-parser'; | |
export const htmlSvgToPdfSvg = (children) => { | |
const svgString = ReactDom | |
.renderToStaticMarkup(children) | |
.replaceAll('px', 'pt'); | |
const [component] = reactHtmlParser(svgString, { transform: convertToPdfSvg }); | |
return component; | |
}; | |
function convertToPdfSvg(node, index) { | |
if (node.type == 'text') { | |
return node.data; | |
} | |
node.props = { key: index }; | |
Object.entries(node.attribs).forEach(([key, value]) => { | |
const [first, ...rest] = key.split('-'); | |
const newKey = [first, ...rest.map(word => `${word[0].toUpperCase()}${word.slice(1)}`)].join(''); | |
node.props[newKey] = value; | |
}); | |
node.name = node.name?.toUpperCase(); | |
if (node.name == 'CLIPPATH') node.name = 'CLIP_PATH'; | |
// we're removing nested <defs> because they don't work | |
if (node.name == 'DEFS' && node.parent.name != 'SVG') return null; | |
if (node.children) node.children = node.children.map(convertToPdfSvg); | |
return createElement(node.name, node.props, node.children); | |
} | |
export default htmlSvgToPdfSvg; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"@react-pdf/renderer": "^2.0.16", | |
"react": "^17.0.2", | |
"react-dom": "^17.0.2", | |
"react-html-parser": "^2.0.2", | |
"recharts": "^2.0.9" | |
} | |
} |
I'm having the same issue with renderFn. Anyone figure this out?
I degraded the version react-pdf ,and it worked
BarChart doesn't work properly, ni the PieChart
@omarhsounalogient
You need to add isAnimationActive={false} when rendering BarChart and PieChart component in the browser. For example -
<Bar isAnimationActive={false} dataKey="uv" fill="#8884d8" />
<Pie isAnimationActive={false} dataKey="value" nameKey="name" cx="25%" cy="50%" outerRadius={50} fill="#000" label />
Hope it helps!
You save my life, after like 4 hours with this issue your advice work
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@omarhsounalogient
You need to add isAnimationActive={false} when rendering BarChart and PieChart component in the browser.
For example -
<Bar isAnimationActive={false} dataKey="uv" fill="#8884d8" />
<Pie isAnimationActive={false} dataKey="value" nameKey="name" cx="25%" cy="50%" outerRadius={50} fill="#000" label />
Hope it helps!