reactjsreact-pdfreact-pdfrenderer

how to display svg image in react-pdf?


How to display svg images in react-pdf and add color styles. but it's doesn't work. this is my code

import { Image } from '@react-pdf/renderer';
import phoneEnable from 'assets/img/icons/phone_enabled.svg';

return(
 <Image
      src={phoneEnable}
      style={{
        height: 8,
        width: 8,
        color: 'red'
      }}
    />

Solution

  • The component from the react-pdf library only supports png and jpg formats for the src prop. If you need to render an SVG file from a URL in your PDF, you'll need to first convert the SVG to a compatible format, like PNG.

    Below is the approach that worked for me when generating PDFs in www.penna.app:

    Hope it helps, i spent a lot of time figuring out the problem...

    *

    import {
      PDFViewer,
      Document,
      Page,
      Text,
      View,
      StyleSheet,
      PDFDownloadLink,
      Link,
      Image,
      Font,
      Svg,
    } from '@react-pdf/renderer';
    import { Canvg } from 'canvg';
    
    /* Fetches the SVG content from a given URL */
    const fetchSvgContent = async (url) => {
      try {
        const response = await fetch(url);
        if (!response.ok) {
          throw new Error(`Failed to fetch SVG: ${response.statusText}`);
        }
        const svgContent = await response.text();
        return svgContent;
      } catch (error) {
        console.error('Error fetching SVG:', error);
        return null;
      }
    };
    
    const svgToDataUri = async (svgString) => {
      try {
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        if (context) {
          const v = Canvg.fromString(context, svgString.trim());
          await v.render();
          const dataUri = canvas.toDataURL('image/png');
          return dataUri;
        }
      } catch (error) {
        console.error('Error occurred:', error);
        return null;
      }
    };
    
    const SVGImage = ({ uri }) => {
      const [svgDataUri, setSvgDataUri] = useState('');
    
      useEffect(() => {
        let isMounted = true;
        async function convertSvgToDataUri() {
          const svg = await fetchSvgContent(uri); // Fetch SVG content
          if (svg) {
            const dataUri = await svgToDataUri(svg);
            if (isMounted) setSvgDataUri(dataUri || '');
          }
        }
    
        convertSvgToDataUri();
    
        return () => {
          isMounted = false;
        };
      }, [uri]);
    
      return (
        svgDataUri !== '' && (
          <Image
            src={svgDataUri}
            style={{ width: 'auto', height: 24 }}
          />
        )
      );
    };
    
    const PDF = () => (
      <PDFViewer style={{ width: '100%', height: '100%' }}>
        <Document>
          <Page size="A4" style={[styles.page, { padding: '80 20' }]}>
            <View style={{ width: 'auto', height: 24 }}>
              <SVGImage
                uri={uri_of_the_svg} /* like 'https://aws.s3.com/bucket/file.svg' */
              />
            </View>
          </Page>
        </Document>
      </PDFViewer>
    );

    *