Skip to content
Advertisement

Print canvas contents

var print = document.createElement('button');
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');

canvas.width = 300;
canvas.height = 100;

ctx.fillStyle = '#000';
ctx.font = '15px sans-serif';
ctx.fillText('Fill Text, 18px, sans-serif', 10, 20);

print.innerHTML = 'Print';

document.body.appendChild(print);
document.body.appendChild(canvas);

print.addEventListener('click', function () {
    window.print();
});

http://jsfiddle.net/vpetrychuk/LWup5/.

As you can see text in the canvas displays ok, but after clicking “Print” button (and saving page as PDF) output image becomes ugly.

Any chance to print the canvas contents without blur?

Advertisement

Answer

You need to make the actual canvas at print size then scale it on screen using CSS rules.

The browser will always use the internal bitmap size first and adjust that to the print or screen. If the bitmap is then of high resolution you will get better result on the print.

But mind you though, you will need to scale every coordinate and size when you print to the canvas. You will also need to prioritize screen versus print as one of them will look worse (if you prioritize print it will not look super on screen and vica verse).

Here is a modified example of your canvas which is now equivalent of 300 DPI (versus default 96 DPI). You can see it looks about the same on screen but will be much sharper when you print it.

/// conversion factor for scale, we want 300 DPI in this example
var dpiFactor = 300 / 96,
    width = 400,
    height = 100;

/// set canvas size representing 300 DPI
canvas.width = width * dpiFactor;
canvas.height = height * dpiFactor;

/// scale all content to fit the 96 DPI display (DPI doesn't really matter here)
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';

/// scale all sizes incl. font size
ctx.font = (15 * dpiFactor).toFixed(0) + 'px sans-serif';

/// scale all positions
ctx.fillText('Fill Text, 18px, sans-serif', 10 * dpiFactor, 20 * dpiFactor);

Simply use wrapper functions to do all the math for you:

function fillText(txt, x, y) {
    ctx.fillText(txt, x * dpiFactor, y * dpiFactor);
}
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement