2014-06-24 23 views
5

Używam Raphaela do narysowania obiektu, a następnie przeniesienia go do elementu canvas HTML za pomocą canvg, dzięki czemu mogę użyć doDataURL, aby zapisać go jako PNG. Ale kiedy używam canvg, wynikowy obraz jest zamazany. Kod poniżej, na przykład, ten sposób uzyskuje się (Raphael na górze, na dole canvg)Kanwa generowana przez canvg jest rozmazana na ekranie siatkówki

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> 

efekt rozmazania jest widoczna w PNG utworzonej przez toDataURL również. Masz pojęcie, co tu się dzieje? Nie sądzę, żeby miało to coś wspólnego z ponownym dopasowaniem. Próbowałem ustawić ignoreDimensions: True i kilka innych rzeczy.

Kolejny punkt danych. Jeśli użyję raphael do wypisania jakiegoś tekstu, a następnie użycia canvg, to jest nie tylko rozmazany, ale także niewłaściwa czcionka!

enter image description here

A oto test.rect (0.5,0.5,50,50) sugeruje. Nadal rozmyte:

enter image description here

+0

Wydaje być mniej rozmyte, jeśli prostokąt jest dość duży. Poza tym nie dowiedziałem się wiele. – AustinC

+0

Bez przeprowadzania jakichkolwiek testów zastanawiam się, jaki jest wynik, gdy szerokość obrysu wynosi 2 piksele. Założę się, że masz do czynienia z problemem półpiksela. – ericjbasti

+0

Jak wygląda kod toDataURL? Upewnij się, że nie jest ustawiony na JPEG. Pliki JPEG są zasysane do grafiki liniowej. – ericjbasti

Odpowiedz

9

więc zajęło mi to trochę czasu, ale wtedy mnie olśniło. Wszystkie twoje przykładowe obrazy są dwa razy większe niż twierdzi kod. Więc najprawdopodobniej znajdujesz się na jakimś urządzeniu HDPI (Retina MacBook Pro itd.) SVG jest świetny, ponieważ niezależny od rozdzielczości, płótno z drugiej strony nie jest. Problem, który widzisz, ma związek z renderowaniem kanwy. Aby to naprawić, musisz przygotować płótno, aby rysunek był wykonany z rozdzielczością ekranu.

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

Ten jsbin przykład powinien wyglądać świetnie na każdym ekranie.

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; 

Należy wyjaśnić kwestię jesteś mający, i miejmy nadzieję skierować Cię w dobrym kierunku, aby go naprawić.

+0

Dzięki za miły przykład Eric! – AustinC

3

Innym rozwiązaniem opisanego in this article, podobną do tej, zamieszczonych tutaj, oprócz tego, że używa scale() i to biorąc pod uwagę stosunek pikseli sklepu podkładowej (przeglądarka bazowego przechowywanie płótnie):

var devicePixelRatio = window.devicePixelRatio || 1, 
    backingStoreRatio = context.webkitBackingStorePixelRatio || 
         context.mozBackingStorePixelRatio || 
         context.msBackingStorePixelRatio || 
         context.oBackingStorePixelRatio || 
         context.backingStorePixelRatio || 1, 

    ratio = devicePixelRatio/backingStoreRatio; 

// upscale the canvas if the two ratios don't match 
if(devicePixelRatio !== backingStoreRatio){ 

    // adjust the original width and height of the canvas 
    canvas.width = originalWidth * ratio; 
    canvas.height = originalHeight * ratio; 

    // scale the context to reflect the changes above 
    context.scale(ratio, ratio); 
} 

// ...do the drawing here... 

// use CSS to bring the entire thing back to the original size 
canvas.style.width = originalWidth + 'px'; 
canvas.style.height = originalHeight + 'px'; 
+0

Pracowałem jak wdzięk, dzięki! –