在Firefox中在HTML画布中绘制调整大小的SVG图像

5

我希望将调整大小的SVG图像绘制到HTML画布中。

在Chromium中,它可以很好地工作,但在Firefox中不行。在Firefox中,图像会变得像素化。

这是SVG图像:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="200" viewbox="0 0 200 200">
  <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
</svg>

以下是代码:

<!DOCTYPE html>
<html>
    <head>
        <title>Resized SVG in Canvas</title>
        <meta charset="utf-8"/>

        <script>
        window.addEventListener('load', function() {
            var canvas = document.getElementById('canvas'),
                context = canvas.getContext('2d'),
                image = new Image();
            image.src = 'circle1.svg';
            image.height = 400;
            image.width = 400;

            image.addEventListener('load', function() {
                try {
                    context.drawImage(image, 0, 0, 400, 400);
                }
                catch(error) {
                    console.log(error);
                }
            }, false);
        }, false);
        </script>
    </head>
    <body>
        <canvas height="600" id="canvas" width="600"></canvas>
    </body>
</html>

结果如下:

结果是:

enter image description here

我希望在Firefox中像在Chromium中一样没有像素失真地绘制调整大小的SVG图像。

目前,我将<img/>放在画布顶部以获取没有像素失真的SVG图像,但由于有很多图像,这样做非常慢。


你是否考虑过使用本地画布API绘制圆形:context.arc(x,y,radius,0,Math.PI*2,false)?许多SVG基本形状在画布中也是可用的,甚至路径也相对容易转换。 - markE
1
这只是一个例子。我想绘制更复杂的SVG图像。 - antoyo
这是一个很好的问题,它显示出Firefox的Gecko渲染引擎会立即将SVG转换为位图,而Webkit则保留其作为SVG,并在需要时直接呈现。这就解释了为什么我的20000个单位宽的SVG即使绘制为400像素宽,在Firefox中也无法呈现。但在Webkit上运行良好。 - Shaun Lebron
1个回答

5

我终于找到了一种在Firefox中在画布上绘制调整大小的SVG的方法。思路是通过AJAX获取SVG源代码,并使用JavaScript更改SVG,例如:

var transformTag;

transformTag = $(document.createElementNS('http://www.w3.org/2000/svg', 'g'))
    .attr('transform', 'scale(' + scaleX + ', ' + scaleY + ')');

svgElement.attr({
    'height': dh,
    'viewbox': '0 0 ' + dw + ' ' + dh,
    'width': dw
})
    .wrapInner(transformTag);

这里有一个jsFiddle(不包含AJAX,但更改简单)。
由于修改和图像创建较慢,我添加了一个简单的缓存机制(未在fiddle中显示,但很容易实现),速度非常快。
它可以在Chromium,Firefox和Opera中使用(但由于某些原因,fiddle在Opera中不起作用,尽管它在我的开发服务器上运行正常)。
附言:如果有一个jQuery替代document.createElementNS,我想知道。

1
这里是一个不需要jQuery的第一版,以防有人需要:https://jsfiddle.net/82auztsy/ - Howard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接