从没有抗锯齿的 svg 创建静态 png,有或没有 canvas

Create static png from svg without Anti-aliasing, with or without canvas

我想要的

我想获取一个矢量 SVG 图像并从中创建一个光栅 png,而不使用抗锯齿。 svg 将根据用户输入(文本、粗体、字体系列)动态生成。 png 是首选,但也可以接受其他光栅格式。

我正在尝试什么

var svg = '<svg><g><text>Hello World</text></g></svg>';
var img = document.createElement('img');
img.setAttribute('src','data:image/svg+xml;base64,' + btoa(svg_static_data) );
img.onload = function() {
    ctx.drawImage(img, 0, 0);
    ctx.mozImageSmoothingEnabled = false;
    ctx.webkitImageSmoothingEnabled = false;
    ctx.msImageSmoothingEnabled = false;
    ctx.imageSmoothingEnabled = false;
    static_image = canvas.toDataURL('image/png');
};

这里的svg很简单,只是为了演示。在这里,我将 svg 转换为 canvas 元素,并将 canvas 元素转换为图像。当这导致抗锯齿时,我发现唯一可能有帮助的配置是 imageSmoothingEnabled,但是我仍然得到抗锯齿,可能是因为该配置是针对使用 canvas 本身绘制的元素。我也试过将该配置放在 drawImage 之上,但没有成功。

我需要什么

将可能包含许多元素和属性(包括弯曲文本)的动态非动画 SVG 转换为至少大部分相同的光栅图像的函数。

我相信这个问题虽然略有不同,但它解释了为什么不能在 SVG 上使用 drawImage 方法。希望对您有所帮助:Is there an equivalent of canvas's toDataURL method for SVG?

imageSmoothingEnabled 仅适用于图像,但仅当图像源按比例绘制时。

但是,这种情况下的问题是 SVG 图像在光栅化之前 在内部消除锯齿 onload 处理程序启动,所以当您将它绘制到 canvas 时,它已经消除锯齿了——除了手动解析和渲染 SVG(这不是一个小项目)之外,您无法关闭它。

在 alpha 通道 () 上使用巧妙的过滤技术,您可以 "un-alias" SVG 中的所有元素,然后再将其渲染到 canvas。只需将其插入 <svg> 元素的顶部:

<defs>
    <filter id="crispify">
        <feComponentTransfer>
            <feFuncA type="discrete" tableValues="0 1"/>
        </feComponentTransfer>
    </filter>
</defs>
<style>
    svg * {
        filter: url('#crispify');
    }
</style>

JSFiddle:https://jsfiddle.net/uqfgs477/1

适用于 Chrome 和 Edge,不适用于 Firefox。