How to draw SVG image on canvas with Konva
How to show SVG image on canvas?
It has not always been possible for browsers to draw *.svg images onto the canvas. However, the situation has improved and you currently have several options available if you want to render a vector image with Konva:
Option 1: Use Konva.Image
In most of the cases you can use *.svg image the same way as any other image such as *.png or *.jpg. You can use Konva.Image shape.
Konva.Image.fromURL('/image.svg', (image) => {
layer.add(image);
});
This method works well in many cases, but is not fully cross-compatible. For example, some SVG may not be visible in the Firefox browser (there is a workaround for that case).
Option 2: Use Konva.Path
Use Konva.Path. This method is good for simple path shapes. If you have a large SVG with many paths you, you may need to split it manually into several Konva.Path shapes.
Option 3: Use an external library to render SVG to canvas
Use an external library (for example, canvg) to draw the SVG into the <canvas> element. And then use that canvas for Konva.Image.
This method has been tested in at least one large production app, with proven reliability and rendering accuracy.
Demo
Below is a demo that shows drawing natively and with a library.
- Vanilla
- React
- Vue
import Konva from 'konva';
import { Canvg } from 'canvg';
const stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight,
});
const layer = new Konva.Layer();
stage.add(layer);
const SOURCE = 'https://konvajs.org/assets/tiger.svg';
// try to draw SVG natively
Konva.Image.fromURL(SOURCE, (imageNode) => {
layer.add(imageNode);
imageNode.setAttrs({
width: 150,
height: 150,
});
});
// draw svg with external library
async function renderWithCanvg() {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const renderer = await Canvg.from(context, SOURCE);
await renderer.render();
const image = new Konva.Image({
image: canvas,
x: 200,
width: 150,
height: 150,
});
layer.add(image);
}
renderWithCanvg().catch((error) => {
console.error('Failed to render SVG:', error);
});
import React from 'react';
import { Stage, Layer, Image } from 'react-konva';
import { useImage } from 'react-konva-utils';
import { Canvg } from 'canvg';
const SOURCE = 'https://konvajs.org/assets/tiger.svg';
const App = () => {
const [nativeImage] = useImage(SOURCE);
const [canvgImage, setCanvgImage] = React.useState(null);
React.useEffect(() => {
let active = true;
const renderWithCanvg = async () => {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const renderer = await Canvg.from(context, SOURCE);
await renderer.render();
if (active) setCanvgImage(canvas);
};
renderWithCanvg().catch((error) => {
console.error('Failed to render SVG:', error);
});
return () => {
active = false;
};
}, []);
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
{nativeImage && (
<Image
image={nativeImage}
width={150}
height={150}
/>
)}
{canvgImage && (
<Image
image={canvgImage}
x={200}
width={150}
height={150}
/>
)}
</Layer>
</Stage>
);
};
export default App;
<template>
<v-stage :config="stageConfig">
<v-layer>
<v-image
v-if="nativeImage"
:config="{
image: nativeImage,
width: 150,
height: 150
}"
/>
<v-image
v-if="canvgImage"
:config="{
image: canvgImage,
x: 200,
width: 150,
height: 150
}"
/>
</v-layer>
</v-stage>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { useImage } from 'vue-konva';
import { Canvg } from 'canvg';
const SOURCE = 'https://konvajs.org/assets/tiger.svg';
const [nativeImage] = useImage(SOURCE);
const canvgImage = ref(null);
let isUnmounted = false;
const stageConfig = {
width: window.innerWidth,
height: window.innerHeight
};
onMounted(async () => {
try {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const renderer = await Canvg.from(context, SOURCE);
await renderer.render();
if (!isUnmounted) canvgImage.value = canvas;
} catch (error) {
if (!isUnmounted) console.error('Failed to render SVG:', error);
}
});
onUnmounted(() => {
isUnmounted = true;
});
</script>
Instructions: The demo shows two SVG images rendered in different ways:
- Left image: Native SVG rendering using Konva.Image
- Right image: SVG rendered using canvg library