HTML5 Canvas Export to High Quality Image Tutorial
If you need to export a stage as an image or as base64 then you can use the stage.toDataURL()
or stage.toImage()
methods.
By default in Konva
, exported images have the pixelRatio
attribute set to 1
. This means that if you export a stage with a size of 500x500
, then the exported image will have the same size of 500x500
.
In some cases you may want to export an image that is more suited to higher (or even smaller) resolutions. For instance, you may wish to export something as an image and then use that image on a canvas on HDPI devices (with a high pixel ratio, like a retina display). Another scenario may be that you need to export a user's drawing onto a computer running a high resolution.
If you were to do this with the default settings, then you would see a blurred image. You can read more about the global pixelRatio
attribute here MDN - devicePixelRatio.
For both of these use cases, you can use:
stage.toDataURL({
pixelRatio: 2
})
Now, a stage with a size of 500x500
would be exported as an image with a size of 1000x1000
. Almost all nodes in Konva
are stored as vector data, apart from bitmap images and cached nodes. This results in a high quality exported image.
Instructions: try to save stage as an image. You will see that it has a high resolution.
import Konva from 'konva';
const stage = new Konva.Stage({
container: 'container',
width: 400,
height: 400
});
const layer = new Konva.Layer();
stage.add(layer);
const circle = new Konva.Circle({
x: 200,
y: 200,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
});
const text = new Konva.Text({
x: 150,
y: 190,
text: 'High Quality Export',
fontSize: 20,
fill: 'white'
});
layer.add(circle);
layer.add(text);
const button = document.createElement('button');
button.textContent = 'Save as High Quality Image';
document.body.appendChild(button);
button.addEventListener('click', () => {
const dataURL = stage.toDataURL({
pixelRatio: 2
});
const link = document.createElement('a');
link.download = 'stage.png';
link.href = dataURL;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
import { Stage, Layer, Circle, Text } from 'react-konva';
import { useRef } from 'react';
const App = () => {
const stageRef = useRef(null);
const handleExport = () => {
const dataURL = stageRef.current.toDataURL({
pixelRatio: 2
});
const link = document.createElement('a');
link.download = 'stage.png';
link.href = dataURL;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
return (
<div>
<button onClick={handleExport} style={{ marginBottom: '10px' }}>
Save as High Quality Image
</button>
<Stage width={400} height={400} ref={stageRef}>
<Layer>
<Circle
x={200}
y={200}
radius={70}
fill="red"
stroke="black"
strokeWidth={4}
/>
<Text
x={150}
y={190}
text="High Quality Export"
fontSize={20}
fill="white"
/>
</Layer>
</Stage>
</div>
);
};
export default App;
<template>
<div>
<button @click="handleExport" style="margin-bottom: 10px">
Save as High Quality Image
</button>
<v-stage ref="stageRef" :config="stageSize">
<v-layer>
<v-circle :config="circleConfig" />
<v-text :config="textConfig" />
</v-layer>
</v-stage>
</div>
</template>
<script setup>
import { ref } from 'vue';
const stageSize = {
width: 400,
height: 400
};
const circleConfig = {
x: 200,
y: 200,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
};
const textConfig = {
x: 150,
y: 190,
text: 'High Quality Export',
fontSize: 20,
fill: 'white'
};
const stageRef = ref(null);
const handleExport = () => {
const dataURL = stageRef.value.getNode().toDataURL({
pixelRatio: 2
});
const link = document.createElement('a');
link.download = 'stage.png';
link.href = dataURL;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
</script>