János
János

Reputation: 35114

How to convert SVG to PNG in React?

I tried with this library: https://www.npmjs.com/package/convert-svg-to-png

But it reaise an error:

import { convert } from 'convert-svg-to-png'

    useEffect(() => {
        let png = convert('/iStock-1188768310.svg')
        console.log(png)
    })
Error: Module not found: Can't resolve 'fs'

Import trace for requested module:
./node_modules/tar-fs/index.js
./node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserFetcher.js
./node_modules/puppeteer/lib/cjs/puppeteer/node/Puppeteer.js
./node_modules/puppeteer/lib/cjs/puppeteer/initialize-node.js

What do I wrong, or is it any more 'standard' way to do it? My goal is to use the image az an og:image. I heard SVG can not be used, this is why I try convert to PNG.


I tried this package also: https://github.com/canvg/canvg Like this:

const canvas = document.querySelector('canvas')
        const ctx = canvas.getContext('2d')

        v = await Canvg.from(ctx, './svgs/1.svg')

        // Start SVG rendering with animations and mouse handling.
        v.start()

But it also raise error:

TypeError: Cannot read properties of null (reading 'getContext')
  24 |  let cv = async () => {
  25 |      const canvas = document.querySelector('canvas')
> 26 |      const ctx = canvas.getContext('2d')
     |                        ^
  27 | 
  28 |      v = await Canvg.from(ctx, './sv

Upvotes: 0

Views: 11492

Answers (4)

Abhishek Singh
Abhishek Singh

Reputation: 43

Here is some function which you use in react native to convert SVG to PNG basically first we convert SVG file into base64 data and Convert it into PNG file and store in local store you are able to see file location in pngDataUri

// these function is used to convert SVG image to PNG image

const convertSvgToImage = async (svgContent) => {
    try {
      const pngDataUri = await convertSvgToPng(svgContent, 400, 400);
      // console.log(pngDataUri.toDataURL());
      console.log('PNG Data URL:', pngDataUri)
      const fileExists = await FileSystem.getInfoAsync(pngDataUri);
      console.log(fileExists);
      if (fileExists.exists) {
        // The file exists, you can read or manipulate it here
        // For example, you can copy it to another location
        console.log(FileSystem.documentDirectory)
        const base64Data = await FileSystem.readAsStringAsync(fileExists.uri, {
          encoding: 'base64',
        });
        const dataUri = `data:image/png;base64,${base64Data}`;
        // console.log("Data URI is "+dataUri);
        setbase64(dataUri);
        return dataUri;
      };
    } catch (error) {
      console.error('Conversion failed:', error);
    }
  };
  const captureView = async (view, width, height) => {3
    return new Promise((resolve, reject) => {
      ref.current.capture().then(uri => {
        resolve(uri);
      }).catch(error => {
        reject(error);
      });
    });
  };
  const convertSvgToPng = async (svgXml, width, height) => {
    return new Promise((resolve, reject) => {
      try {
        const svgDataUri = `data:image/svg+xml;base64,${btoa(svgXml)}`;
        console.log("svgData is = ",svgDataUri);
        const img = Image.resolveAssetSource({ uri: svgDataUri });
        img.width = width;
        img.height = height;
  
        const result = captureView(img, width, height);
        
        resolve(result);
      } catch (error) {
        reject(error);
        console.log("errror in cathc")
      }
    });
  };

use ViewShot for get ref of SVG Img

<ViewShot ref={ref}>
  <Svg width="100%" height="100%">
     {renderPaths()}
     {currentPath.length > 1 && (
       <Path
          d={`M${currentPath.map(p => `${p.x},${p.y}`).join(' L')}`}
          fill="none"
          stroke="black"
          strokeWidth={2}
        />
       )}
     </Svg>
 </ViewShot>

Upvotes: 1

chrwahl
chrwahl

Reputation: 13153

Here you have an (client-side) example of how an SVG document can be loaded using fetch() (if the SVG is not already in the DOM), turned into a File object, drawn on a canvas and expoted as a PNG.

var svgcontainer, svg, canvas, ctx, output;

document.addEventListener('DOMContentLoaded', e => {
  svgcontainer = document.getElementById('svgcontainer');
  canvas = document.getElementById('canvas');
  output = document.getElementById('output');
  ctx = canvas.getContext('2d');
  fetch('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI1MCIgZmlsbD0ib3JhbmdlIiAvPgo8L3N2Zz4KCgo=').then(res => res.text()).then(text => {
    let parser = new DOMParser();
    let svgdoc = parser.parseFromString(text, "application/xml");
    canvas.width = svgdoc.rootElement.getAttribute('width');
    canvas.height = svgdoc.rootElement.getAttribute('height');

    // append SVG to DOM
    svgcontainer.innerHTML = svgdoc.rootElement.outerHTML;
    svg = svgcontainer.querySelector('svg');

    // create a File object
    let file = new File([svgdoc.rootElement.outerHTML], 'svg.svg', {
      type: "image/svg+xml"
    });
    // and a reader
    let reader = new FileReader();

    reader.addEventListener('load', e => {
      /* create a new image assign the result of the filereader
      to the image src */
      let img = new Image();
      // wait for it to got load
      img.addEventListener('load', e => {
        // update canvas with new image
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(e.target, 0, 0);
        // create PNG image based on canvas
        let img = new Image();
        img.src = canvas.toDataURL("image/png");
        output.append(img);
      });
      img.src = e.target.result;
    });
    // read the file as a data URL
    reader.readAsDataURL(file);
  });
});
<div style="display:flex">
  SVG:
  <div id="svgcontainer"></div>
  Canvas: <canvas id="canvas" width="200" height="200"></canvas>
</div>
<p>Exported PNG:</p>
<div id="output"></div>

Upvotes: 0

Cedric Agoliki
Cedric Agoliki

Reputation: 1

The title says "A Node.js package for converting SVG to PNG using headless Chromium". You can only use it in nodejs not in client-side JavaScript. You may want to check this answer if you want to do it in the browser: Convert SVG to image (JPEG, PNG, etc.) in the browser.

Upvotes: 0

Zejj
Zejj

Reputation: 66

according to the library's npm page, the function you need to import is convertFile and not convert:

const { convertFile}  = require('convert-svg-to-png');

The following code should work:

(async() => {
  const inputFilePath = '/path/to/my-image.svg';
  const outputFilePath = await convertFile(inputFilePath);

  console.log(outputFilePath);
  //=> "/path/to/my-image.png"
})();

Upvotes: 1

Related Questions