HTML5 Canvas Export to High Quality Image Tutorial

How to export a high quality image from a stage?

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 // or other value you need
})

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.

Usage: try to save stage as an image. You will see that it has a high resolution.

Konva Pixel Ratio Demoview raw
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/[email protected]/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva High Quality Export Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}

#buttons {
position: absolute;
top: 5px;
left: 10px;
}

#buttons > input {
padding: 10px;
display: block;
margin-top: 5px;
}
</style>
</head>

<body>
<div id="container"></div>
<div id="buttons"><button id="save">Save as image</button></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;

var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});

var layer = new Konva.Layer();
stage.add(layer);

var box = new Konva.Rect({
x: stage.width() / 2 - 50,
y: stage.height() / 2 - 25,
width: 100,
height: 50,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 4,
draggable: true,
});
layer.add(box);

var circle = new Konva.Circle({
x: stage.width() - 50,
y: stage.height() - 50,
radius: 50,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
});
layer.add(circle);

layer.draw();

// function from https://stackoverflow.com/a/15832662/512042
function downloadURI(uri, name) {
var link = document.createElement('a');
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}

document.getElementById('save').addEventListener(
'click',
function () {
var dataURL = stage.toDataURL({ pixelRatio: 3 });
downloadURI(dataURL, 'stage.png');
},
false
);
</script>
</body>
</html>
Enjoying Konva? Please consider to support the project.