Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
283 views
in Technique[技术] by (71.8m points)

javascript - Canvas generated by canvg is blurry on retina screen

I'm using Raphael to draw an object, then transferring it to an HTML canvas element with canvg so that I can use toDataURL to save it as a PNG. But when I use canvg, the resulting image is blurry. The code below, for example, produces this (raphael on top, canvg on bottom):

enter image description here

<html>
    <head>
        <script src="lib/raphael-min.js"></script>
        <script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js"></script> 
        <script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/StackBlur.js"></script>
        <script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/canvg.js"></script> 
        <script src="lib/raphael.export.js"></script>
    </head>
    <body>

    <div id="raph_canvas"></div><br> 
    <canvas id="html_canvas" width="50px" height="50px"></canvas>

    <script language="JavaScript">
    var test=Raphael("raph_canvas",50,50);
    var rect=test.rect(0,0,50,50);
    rect.attr({fill: '#fff000', 'fill-opacity':1, 'stroke-width':1})

    window.onload = function() {
        var canvas_svg = test.toSVG();
        canvg('html_canvas',canvas_svg);
        var canvas_html = document.getElementById("html_canvas");
    }

    </script>
    </body>
</html>

The blurriness is evident in the png created by toDataURL as well. Any idea what is going on here? I don't think this has anything to do with re-sizing. I've tried setting ignoreDimensions: True and some other things.

Another datapoint. If I use raphael to output some text and then use canvg, it is not only blurry but the wrong font!

enter image description here

And here is the test.rect(0.5,0.5,50,50) suggested. Still blurry:

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So it took me a while, but then it dawned on me. All your example images are twice the size the code claims they should be. So you're most likely on some sort of HDPI device (Retina MacBook Pro ect...) SVG is great because its resolution independent, canvas on the other hand is not. The issue you're seeing has to do with how canvas renders. To fix this, you need to prep the canvas so that your drawing will be done at the resolution of your screen.

http://jsbin.com/liquxiyi/3/edit?html,js,output

This jsbin example should look great on any screen.

The trick:

var cv = document.getElementById('box');
var ctx = cv.getContext("2d");

// SVG is resolution independent. Canvas is not. We need to make our canvas 
// High Resolution.

// lets get the resolution of our device.
var pixelRatio = window.devicePixelRatio || 1;

// lets scale the canvas and change its CSS width/height to make it high res.
cv.style.width = cv.width +'px';
cv.style.height = cv.height +'px';
cv.width *= pixelRatio;
cv.height *= pixelRatio;

// Now that its high res we need to compensate so our images can be drawn as 
//normal, by scaling everything up by the pixelRatio.
ctx.setTransform(pixelRatio,0,0,pixelRatio,0,0);


// lets draw a box
// or in your case some parsed SVG
ctx.strokeRect(20.5,20.5,80,80);

// lets convert that into a dataURL
var ur = cv.toDataURL();

// result should look exactly like the canvas when using PNG (default)
var result = document.getElementById('result');
result.src=ur;

// we need our image to match the resolution of the canvas
result.style.width = cv.style.width;
result.style.height = cv.style.height;

This should explain the issue you're having, and hopefully point you in a good direction to fix it.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...