将组件重新打包为PNG

Col*_*ole 5 javascript canvas reactjs recharts

我目前有一个Recharts组件,我想将其导出为PNG文件。

                    <LineChart
                        id="currentChart"
                        ref={(chart) => this.currentChart = chart}
                        width={this.state.width}
                        height={this.state.height}
                        data={this.testData}
                        margin={{top: 5, right: 30, left: 20, bottom: 5}}
                    >
                        <XAxis dataKey="name"/>
                        <YAxis/>
                        <CartesianGrid strokeDasharray="3 3"/>
                        <Tooltip/>
                        <Legend />
                        <Line type="monotone" dataKey="pv" stroke="#8884d8" activeDot={{r: 8}}/>
                        <Line type="monotone" dataKey="uv" stroke="#82ca9d"/>
                    </LineChart>
Run Code Online (Sandbox Code Playgroud)

但是我不确定库是否直接支持此功能。

我的想法涉及使用画布和2D渲染上下文使我接近解决方案,如MDN所述

但是,我不确定将HTML元素(或React组件)呈现为画布以实现此解决方案的通用方法。

我可能会把所有这些都弄错了,我将感谢您的纠正!

pet*_*tos 8

此函数在输入中获取 SVG 元素并转换为image/png数据:

export const svgToPng = (svg, width, height) => {

    return new Promise((resolve, reject) => {

        let canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        let ctx = canvas.getContext('2d');

        // Set background to white
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(0, 0, width, height);

        let xml = new XMLSerializer().serializeToString(svg);
        let dataUrl = 'data:image/svg+xml;utf8,' + encodeURIComponent(xml);
        let img = new Image(width, height);

        img.onload = () => {
            ctx.drawImage(img, 0, 0);
            let imageData = canvas.toDataURL('image/png', 1.0);
            resolve(imageData)
        }

        img.onerror = () => reject();

        img.src = dataUrl;
    });
};
Run Code Online (Sandbox Code Playgroud)

以及如何访问 Recharts SVG 元素?此代码片段允许您呈现当前可见 DOM 之外的任何图表并使用它的 SVG:

const exportChart = () => {

    // Output image size
    const WIDTH = 900;
    const HEIGHT = 250;

    const convertChart = async (ref) => {

        if (ref && ref.container) {
            let svg = ref.container.children[0];
            let pngData = await svgToPng(svg, WIDTH, HEIGHT);
            console.log('Do what you need with PNG', pngData);
        }
    };

    const chart = <LineChart data={...} width={WIDTH} height={HEIGHT}
        ref={ref => convertChart(ref)} />;

    // Render chart component into helper div
    const helperDiv = document.createElement('tmp');
    ReactDOM.render(chart, helperDiv);
}
Run Code Online (Sandbox Code Playgroud)


Col*_*ole 6

通过研究“图表”组件,我能够解决我的问题。图表在包装器下呈现为SVG,因此我要做的就是正确转换以另存为HTML或SVG

// Exports the graph as embedded JS or PNG
exportChart(asSVG) {

    // A Recharts component is rendered as a div that contains namely an SVG
    // which holds the chart. We can access this SVG by calling upon the first child/
    let chartSVG = ReactDOM.findDOMNode(this.currentChart).children[0];

    if (asSVG) {
        let svgURL = new XMLSerializer().serializeToString(chartSVG);
        let svgBlob = new Blob([svgURL], {type: "image/svg+xml;charset=utf-8"});
        FileSaver.saveAs(svgBlob, this.state.uuid + ".svg");
    } else {
        let svgBlob = new Blob([chartSVG.outerHTML], {type: "text/html;charset=utf-8"});
        FileSaver.saveAs(svgBlob, this.state.uuid + ".html");
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用FileSaver.js作为保存提示。

  • 您在哪里将svg转换为png? (2认同)