0

The Konva.Image.fromURL() method is the only way to render a native SVG mentioned in the documentation. I haven't found any other way to display an SVG from a variable without using 3rd party libraries.

Konva.Path cannot be used as an SVG consists of multiple elements and the library fails to render it correctly.

Using 3rd party libraries is not a good option either, as they reduce the picture quality and are not native methods.

Can anyone help me with finding a native way to render an SVG without compromising its quality, please?

example from docs:

Konva.Image.fromURL('./test.svg', (imageNode) => {
      layerRef.current.add(imageNode);
      imageNode.setAttrs({
        width: 150,
        height: 150,
        x: 10,
        y: 10,
      });
      layerRef.current.batchDraw();

its works

my example:

`const svg = <svg ... </svg>

Konva.Image.create(svg, (imageNode) => {
      layerRef.current.add(imageNode);
       imageNode.setAttrs({
        width: 150,
        height: 150,
        x: 10,
        y: 10,
      });
      layerRef.current.batchDraw();`

code in sandbox

1 Answers1

0

You can convert svg string into data url using this:


function svgToURL(s) {
  const uri = window.btoa(unescape(encodeURIComponent(s)));
  return "data:image/svg+xml;base64," + uri;
}

When you have url of the SVG, you can use it as source for image.

const url = svgToURL(svg);

Full example using react-konva and use-image hook:

import React from "react";
import { Stage, Layer, Image } from "react-konva";
import useImage from "use-image";

function svgToURL(s) {
  const uri = window.btoa(unescape(encodeURIComponent(s)));
  return "data:image/svg+xml;base64," + uri;
}

const svg =
  '<svg width="500" height="100" viewBox="0 0 500 100" xmlns="http://www.w3.org/2000/svg"><path fill="red" d="M3.9 7.8L6.4 7.8L6.4 9.2L3.9 9.2L3.9 18.7L2.3 18.7L2.3 9.2L0.5 9.2L0.5 7.8L2.3 7.8L2.3 6.3Q2.3 5.4 2.7 4.7Q3.2 4.1 3.9 3.8Q4.6 3.5 5.3 3.5L5.3 3.5Q6.0 3.5 6.3 3.6Q6.7 3.7 6.9 3.8L6.9 3.8L6.4 5.2Q6.3 5.2 6.1 5.1Q5.9 5.1 5.5 5.1L5.5 5.1Q4.7 5.1 4.3 5.5Q3.9 5.9 3.9 6.7L3.9 6.7L3.9 7.8ZM11.2 7.8L13.6 7.8L13.6 9.2L11.2 9.2L11.2 18.7L9.5 18.7L9.5 9.2L7.7 9.2L7.7 7.8L9.5 7.8L9.5 6.3Q9.5 5.4 9.9 4.7Q10.4 4.1 11.1 3.8Q11.8 3.5 12.6 3.5L12.6 3.5Q13.2 3.5 13.6 3.6Q14.0 3.7 14.1 3.8L14.1 3.8L13.7 5.2Q13.5 5.2 13.3 5.1Q13.1 5.1 12.7 5.1L12.7 5.1Q11.9 5.1 11.5 5.5Q11.2 5.9 11.2 6.7L11.2 6.7L11.2 7.8ZM18.4 7.8L20.8 7.8L20.8 9.2L18.4 9.2L18.4 18.7L16.7 18.7L16.7 9.2L14.9 9.2L14.9 7.8L16.7 7.8L16.7 6.3Q16.7 5.4 17.1 4.7Q17.6 4.1 18.3 3.8Q19.0 3.5 19.8 3.5L19.8 3.5Q20.4 3.5 20.8 3.6Q21.2 3.7 21.4 3.8L21.4 3.8L20.9 5.2Q20.8 5.2 20.5 5.1Q20.3 5.1 19.9 5.1L19.9 5.1Q19.1 5.1 18.7 5.5Q18.4 5.9 18.4 6.7L18.4 6.7L18.4 7.8Z "/><line x1="0" y1="20.59214501510574" x2="21.647727272727273" y2="20.59214501510574" stroke="red" stroke-width="2" stroke-linecap="square"/></svg>';

const url = svgToURL(svg);

function App() {
  const [image] = useImage(url);

  return (
    <div>
      <Stage
        width={window.innerWidth}
        height={500}
        style={{ border: "4px solid blue" }}
      >
        <Layer>
          <Image image={image} />
        </Layer>
      </Stage>
    </div>
  );
}

export default App;

Demo: https://codesandbox.io/s/happy-bassi-ojmjkl?file=/src/App.js

lavrton
  • 18,973
  • 4
  • 30
  • 63