为什么我的带有 viewBox 和十六进制编码颜色的 SVG 图标在用作 javascript Image() 的“.src”时无法呈现

Why do my SVG icons with viewBox and hex encoded colors fail to render when used as '.src' for javascript Image()

我之前的问题作为重复问题被关闭,但我现在找到了问题的真正答案。

原来的问题是,我想知道为什么我的 .SVG 图标上的十六进制颜色和视图框似乎无法显示。我一直在使用 base64,并且我对 base64 进行了解码,以便我可以更轻松地提出问题,包括以下 fiddle(为了完整性而包含在下面的代码)。第一个图标显示,第二个不显示。

建议十六进制颜色需要使用 %23 进行转义。由于这个原因,这个问题因为重复而被关闭。我不知道如何删除重复的问号,所以我创建了这个新问题来分享我的发现和我自己的答案。

https://jsfiddle.net/pqh0n1mw/1/

var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
ctx.scale(2, 2);

var img1 = new Image();
img1.src = 'data:image/svg+xml;utf8,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><rect stroke="none" fill="rgb(255, 38, 0)" x="0" y="0" width="32" height="32" /><path stroke="none" fill="rgb(250, 250, 250)" d="M 0,8 L 8,8 8,-0 12,-0 12,12 0,12 0,8 Z M 0,8" /><path stroke="rgb(255, 255, 255)" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" fill="none" d="M 1.5,1.5 L 17.5,17.5" /></svg>';

ctx.drawImage(img1, 10, 10);

var img2 = new Image();
img2.src = 'data:image/svg+xml;utf8,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect fill="#FF2600" width="32" height="32"/><path fill="#FAFAFA" d="M0,8 8,8 8,-0 12,-0 12,12 0,12 Z"/><path stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-miterlimit="10" fill="none" d="M1.5,1.5 17.5,17.5"/></svg>';
ctx.drawImage(img2, 42, 10);

事实证明,将十六进制颜色的 # 编码为 %23 会使情况变得更糟,并且 b64 编码的图标不再显示。无论如何,我没有将 data-url 用作 .css 中的 url() ,我认为它可能被视为选择器。

有人还建议使用 codepen 可以解决问题。这也没有用,因为 codepen 转义了颜色甚至尖括号,以这种方式使用的 .svg 不需要这些东西。

所以问题竟然是单独使用'viewBox'。在取自这些图标的另一个平台上工作正常,但在用作 Image().src 属性.

时在 javascript 中不起作用

无论如何,将 'viewBox' 替换为 'width' 和 'height' 属性后,图标现在以原始 base64 编码格式显示,包括使用十六进制编码的颜色。

我希望这能帮助别人,或者当我再次遇到同样的问题时,也许能帮助我未来的自己 :)

var img3 = new Image();
img3.src = "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIj48cmVjdCBmaWxsPSIjRkYyNjAwIiB3aWR0aD0iMzIiIGhlaWdodD0iMzIiLz48cGF0aCBmaWxsPSIjRkFGQUZBIiBkPSJNMCw4IDgsOCA4LC0wIDEyLC0wIDEyLDEyIDAsMTIgWiIvPjxwYXRoIHN0cm9rZT0iI0ZGRkZGRiIgc3Ryb2tlLXdpZHRoPSIzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgZmlsbD0ibm9uZSIgZD0iTTEuNSwxLjUgMTcuNSwxNy41Ii8+PC9zdmc+";
ctx.drawImage(img3, 74, 10);

[更新] 我用最新的 firefox 78.3 进行了测试。0.esr 并看到了类似的行为。我还在 CSS url() 背景中测试了我的图标,当编码为 base64 时,它们可以很好地处理 viewBox 的原始格式(无宽度和高度)和十六进制颜色。所以看起来通过 Image().src 的处理是不同的。

[update2] 如下所述,即使是 b64 编码图像,我也应该使用 onload 回调,因为并非所有浏览器都会立即提供图像。

safe way to access data url image