将svg转换为base64

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将svg转换为base64相关的知识,希望对你有一定的参考价值。

以编程方式创建的SVG无法正确转换为base64。

在我的应用程序中,我有一个服务,该服务使用g-element响应,然后放入创建的svg-element并将其转换为base64,但是如果我尝试打开链接,我会发现svg不会在页面。

    var xmlns = 'http://www.w3.org/2000/svg',
    IMAGE_TEMPLATE = document.createElementNS(xmlns, 'svg');
    IMAGE_TEMPLATE.appendChild(document.body.querySelector('#ico-appliance-thermostat-128'));
    IMAGE_TEMPLATE.setAttribute('id', 'svg');

    IMAGE_TEMPLATE.setAttributeNS(null, 'width', 128);
    IMAGE_TEMPLATE.setAttributeNS(null, 'height', 128);
    IMAGE_TEMPLATE.setAttributeNS(null, 'viewBox', '0 0 128 128');

    document.body.querySelector('#test').appendChild(IMAGE_TEMPLATE);

    test = function(){
        var s = new XMLSerializer().serializeToString(document.getElementById("svg"))
        var encodedData = window.btoa(s);
        console.log('data:image/svg+xml;base64,' + encodedData);
    }

https://jsfiddle.net/6sra5c5L/

答案

@ guest271314和我的回答之间的区别:

@ guest271314他的回答:

将g元素包装在svg元素内,以确保浏览器在加载时呈现g元素。

我的回答:

由于没有在加载时渲染g元素,因此强制#test中的svg元素渲染g元素。

在这种情况下的最佳答案:@ guest271314

原因:g元素应位于有效html中的svg元素内。

什么时候应该使用我的答案?如果g元素不是html文档中的元素。

您没有使用}关闭test()。下面的代码返回base64编码的svg:https://jsfiddle.net/seahorsepip/6sra5c5L/1/

编辑:

svg渲染问题是我之前遇到过的问题,这是一行jquery的解决方法:https://jsfiddle.net/seahorsepip/6sra5c5L/3/

//Force refresh svg
$("#test").html($("#test").html());

这里是关于此问题的原始SO线程:jquery's append not working with svg element?

我不知道我添加的jQuery代码的javascript等效项,我尝试编写它,但没有用:/

编辑2:

这里是纯js等效项:

https://jsfiddle.net/seahorsepip/6sra5c5L/4/

//Force refresh svg
var svg = document.body.querySelector('#test').innerHTML;
document.body.querySelector('#test').innerHTML = "";
document.body.querySelector('#test').innerHTML = svg;
另一答案

尝试在<svg></svg>元素周围添加<g>,并在}功能处关闭test;将test定义为命名函数

    var xmlns = 'http://www.w3.org/2000/svg',
      IMAGE_TEMPLATE = document.createElementNS(xmlns, 'svg');
    IMAGE_TEMPLATE.appendChild(document.body.querySelector('#ico-appliance-thermostat-128'));
    IMAGE_TEMPLATE.setAttribute('id', 'svg');
    IMAGE_TEMPLATE.setAttributeNS(null, 'width', 128);
    IMAGE_TEMPLATE.setAttributeNS(null, 'height', 128);
    IMAGE_TEMPLATE.setAttributeNS(null, 'viewBox', '0 0 128 128');

    document.body.querySelector('#test').appendChild(IMAGE_TEMPLATE);

    function test() {
      var s = new XMLSerializer().serializeToString(document.getElementById("svg"))
      console.log(document.getElementById("svg"))
      console.log(s)
      var encodedData = window.btoa(s);
      console.log('data:image/svg+xml;base64,' + encodedData);
    }
<svg>
  <g id="ico-appliance-thermostat-128" transform="scale(2)">
    <path d="M106.949,128.009 L105.294,124.692 C115.967,119.333 123.298,108.278 123.298,95.500 C123.298,82.722 115.967,71.666 105.294,66.308 L106.949,62.990 C118.835,68.958 126.999,81.270 126.999,95.500 C126.999,109.730 118.835,122.042 106.949,128.009 ZM117.376,95.500 C117.376,105.954 111.378,115.000 102.645,119.384 L100.990,116.067 C108.510,112.292 113.676,104.502 113.676,95.500 C113.676,86.497 108.510,78.708 100.990,74.933 L102.645,71.615 C111.378,76.000 117.376,85.045 117.376,95.500 ZM106.999,95.213 C106.999,98.063 104.756,100.373 101.988,100.373 C100.251,100.373 98.720,99.462 97.822,98.080 L91.490,98.080 L85.840,116.427 L85.662,116.427 L85.840,117.000 L80.829,117.000 L70.082,82.422 L65.795,97.506 L65.795,98.080 L54.999,98.080 L54.999,92.920 L62.087,92.920 L67.465,74.000 L72.477,74.000 L83.234,108.615 L88.067,92.920 L89.738,92.920 L93.079,92.920 L97.504,92.920 C98.324,91.222 100.021,90.053 101.988,90.053 C104.756,90.053 106.999,92.363 106.999,95.213 ZM24.999,128.000 C11.787,128.000 0.999,117.189 0.999,103.993 C0.999,96.779 4.177,90.380 8.986,85.988 C8.986,85.173 8.986,84.776 8.986,83.981 L8.986,15.997 C8.986,7.193 16.177,-0.000 24.979,-0.000 C33.780,-0.000 40.972,7.193 40.972,15.997 L40.972,83.981 C40.972,84.796 40.972,85.194 40.972,85.988 C45.780,90.380 48.979,96.779 48.999,103.993 C48.999,117.210 38.212,128.000 24.999,128.000 ZM33.999,90.000 L33.999,17.000 C33.999,12.373 29.662,8.009 24.988,8.009 C20.314,8.009 16.000,12.373 16.000,17.000 L16.000,90.000 C10.903,92.952 7.985,97.813 7.985,104.136 C7.985,113.411 15.641,120.990 25.011,120.990 C34.380,120.990 42.037,113.389 41.992,104.114 C41.992,97.791 39.118,92.952 33.999,90.000 ZM24.999,112.990 C19.904,112.990 15.999,109.082 15.999,103.983 C15.999,100.092 18.383,96.796 21.989,95.588 C21.989,95.290 21.989,95.290 21.989,94.992 L21.989,38.991 C21.989,37.500 23.181,35.994 24.984,35.994 C26.787,35.994 27.979,37.187 27.979,38.991 L27.979,95.008 C27.979,95.306 27.979,95.306 27.979,95.604 C31.585,96.812 33.984,100.107 33.999,103.983 C33.999,109.082 30.095,112.990 24.999,112.990 Z"
    style="fill: #5aac21;fill-rule: evenodd;"></path>
  </g>
</svg>
<div id="test"></div>
<button onclick="test()">Test</button>
另一答案

HTML元素和SVG元素具有不同的命名空间。通过将<g>元素放入HTML中,您创建了一个<html:g>元素。当它在<svg>内部移动时,它仍然是<html:g>,并且不会被SVG渲染器识别。

您必须按照@ guest271314的说明将其放入soem <svg>标签中。或者,在追加到SVG之后,遍历<g>中的所有元素,并将其所有名称空间更改为SVG。

另一答案

我没有看到完整解释,这里什么地方实际发生了什么,所以就去了。

浏览器将HTML解析为HTML

虽然看起来很明显,但是当您将非HTML(SVG,XML等)元素放入其中时,情况并非如此。

浏览器太好了,当您提供有效的SGML(XML,HTML的父级...)时,他们会根据you会说的内容找到不属于其中的元素(<g>)在那里(HTML)-他们不抱怨,只对待未知的元素作为未知的HTML元素,生成类HTMLUnknownElement

浏览器通常不更改元素对象类

所以您基本上是将HTMLUnknownElement放入HTMLUnknownElement,这将标记内容放入svg,但是由于基础对象不是SVG(SVGSVGElement)的有效子元素,因此不会做任何事情。这就是为什么必须使用命名空间=>创建动态创建的SVGSVGElement的相同原因,当命名空间与SVGGElement元素结合使用时,它告诉浏览器-嘿!此标记来自SVG规范=>将其视为SVG !

解决方案

您当前的示例代码存在语法错误,由于这不是真正的问题,我将不予解决。

静态定义的<svg>模板

如果模板已存在于原始文档中,请强制浏览器通过用<svg>换行将其视为<g>(浏览器可以不使用SVGSVGElement属性来食用它,但这是更安全的方法)。担心会显示吗?只需用CSS <svg xmlns="http://www.w3.org/2000/svg"></svg>隐藏它-它影响渲染

动态定义的xmlns模板

如果要动态创建display: none;元素,则应在使用<g>指定名称空间的同时创建它,例如:

<g>

静态但不可更改的createElementNS()模板

如果您陷于中间并且无法更改静态模板,则仍可以基于动态方法:

  1. 使用正确的名称空间创建新的document.createElementNS('http://www.w3.org/2000/svg', 'g');

    <g>

  2. 获得“原始”旧的<g>-它将是var newGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');,但没关系,因为它是基于<g>构建的,这使我们可以使用enaugh API来传输我们需要的所有东西]

    HTMLUnknownElement

  3. 可能将旧的组属性转移到新的组-方便的是HTMLElement

    HTMLElement

  4. 现在浏览器已经知道newGroup var oldGroup = document.querySelector('oldGroupSelector');的内容实际上是svg-newGroup是element.attributes-现在我们可以重新填充内容

    以上是关于将svg转换为base64的主要内容,如果未能解决你的问题,请参考以下文章

    在节点中将 svg 图像从 url 转换为 base64

    将base64 svg数据解码为svg文件

    使用 <path> 标签将图标图像转换为 svg 的最佳方法

    使用 angularjs 将 svg 中的 xlink:href 设置为 base64 编码的图像

    将图像异步转换为 Base64 的 C# 简单应用程序

    将图像转换为 Json Swift 3 的 Base64