【问题标题】:Load SVG into canvas to get base64 dataurl将SVG加载到画布中以获取base64 dataurl
【发布时间】:2022-01-09 11:36:22
【问题描述】:

我的 html 中有这个 SVG:

<svg xmlns="http://www.w3.org/2000/svg" class="bi flex-shrink-0 me-2 green-check" width="24" height="24" role="img" aria-label="moon"><title>Free</title><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#check-green-symbol"/></svg>

“use”标签指向的符号是:

<symbol id="check-green-symbol" viewBox="0 0 512 512" id=".3539536280039488" xmlns="http://www.w3.org/2000/svg">
    <path d="M437.019 74.981C388.668 26.629 324.38.001 256 .001S123.332 26.629 74.98 74.981C26.629 123.333 0 187.621 0 256.001S26.629 388.669 74.98 437.02C123.332 485.371 187.62 512 256 512c68.381 0 132.668-26.629 181.019-74.98C485.371 388.667 512 324.379 512 255.999s-26.629-132.666-74.981-181.018zM256 477.453C133.891 477.453 34.547 378.11 34.547 256S133.891 34.548 256 34.548s221.453 99.343 221.453 221.453S378.109 477.453 256 477.453z" fill="green" />
     <path d="M393.953 160.709c-21.906-21.904-57.355-21.906-79.264-.001l-89.238 89.239-28.14-28.141c-21.903-21.903-57.354-21.906-79.262 0-21.852 21.852-21.853 57.408 0 79.26l67.772 67.772c10.586 10.586 24.66 16.416 39.631 16.416s29.045-5.83 39.631-16.415l128.87-128.87c21.852-21.851 21.852-57.408 0-79.26zm-24.431 54.832L240.653 344.41c-4.061 4.06-9.459 6.297-15.202 6.297s-11.142-2.237-15.202-6.297l-67.771-67.772c-8.383-8.383-8.383-22.022 0-30.403 8.402-8.401 22-8.404 30.404 0l40.355 40.355a17.274 17.274 0 0 0 24.428 0l101.453-101.453c8.402-8.401 22.002-8.404 30.404 0 8.384 8.383 8.384 22.022 0 30.404z" fill="green" stroke="green" stroke-width="50" />
</symbol>

当页面加载时正确显示(即它使用我使用use标签引用的符号)。

我想获取这个 SVG 并获取 base64 数据 URL(将其转换为图像)。

我尝试使用此代码但没有成功,它总是给我一个白色/空白图像。

function convertSVG(classname) {
    var serializer = new XMLSerializer();
    var svgElement = document.querySelector(".green-check"); //hardcoded for test
    var svgData = new XMLSerializer().serializeToString(svgElement);
    console.log(svgData);
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext("2d");
    var img = new Image;
    img.width  = canvas.width  = svgElement.clientWidth;
    img.height = canvas.height = svgElement.clientHeight;
        img.src = 'data:image/svg+xml,' + encodeURIComponent(svgData);
    ctx.drawImage( img, 0, 0, img.width, img.height );
    console.log(canvas.toDataURL());
    return canvas.toDataURL();
}

我在控制台中得到的 base64 如下所示:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAARZJREFUSEuVVlkWwyAIxPsfOnkqKsiwmJ+2KoFZwDbaTyOi7/zs3+RSsi0D7zDea9To2ynM+8DCOa833QQDAe96xY91gEZDX+gbtXPWjzLJwgT6tEigKR8VJTzhPJZqSItJADiTdHmgFAJcdQLES7ytI6jAjADVjaJcBIBUEvkgk/wmpuBk/cNvtcSynjVlw6oEAHm50fHBjvh+ZNUb5rebq9JjNysJRRWRwahAGhiYoNxK5ytThN3oifwASmjgRx17Ayq43DFZHc1kl0S3Q3BBBD1hqisNmHk3ufNnX12ZTU0XgsGTNM/UICnl1fuqLmM7j6KwCJ5RUmQ1TctzWkSt/wehZZcGFQ4S72OzTPYTa76duDX/Aaq1oyLeMBeVAAAAAElFTkSuQmCC

我还尝试按照“use”标签对元素进行序列化 “Robert Longson”建议,使用这部分代码:

var serializer = new XMLSerializer();
    var svgElement = document.querySelector(".green-check");
    var svgElement2 = document.querySelector("#check-green-symbol");
    svgElement.innerHTML = svgElement2.innerHTML;
    var svgData = new XMLSerializer().serializeToString(svgElement);

序列化后的字符串如下所示:

<svg xmlns="http://www.w3.org/2000/svg" class="bi flex-shrink-0 me-2 green-check" width="24" height="24" role="img" aria-label="moon"> <path d="M437.019 74.981C388.668 26.629 324.38.001 256 .001S123.332 26.629 74.98 74.981C26.629 123.333 0 187.621 0 256.001S26.629 388.669 74.98 437.02C123.332 485.371 187.62 512 256 512c68.381 0 132.668-26.629 181.019-74.98C485.371 388.667 512 324.379 512 255.999s-26.629-132.666-74.981-181.018zM256 477.453C133.891 477.453 34.547 378.11 34.547 256S133.891 34.548 256 34.548s221.453 99.343 221.453 221.453S378.109 477.453 256 477.453z" fill="green"/> <path d="M393.953 160.709c-21.906-21.904-57.355-21.906-79.264-.001l-89.238 89.239-28.14-28.141c-21.903-21.903-57.354-21.906-79.262 0-21.852 21.852-21.853 57.408 0 79.26l67.772 67.772c10.586 10.586 24.66 16.416 39.631 16.416s29.045-5.83 39.631-16.415l128.87-128.87c21.852-21.851 21.852-57.408 0-79.26zm-24.431 54.832L240.653 344.41c-4.061 4.06-9.459 6.297-15.202 6.297s-11.142-2.237-15.202-6.297l-67.771-67.772c-8.383-8.383-8.383-22.022 0-30.403 8.402-8.401 22-8.404 30.404 0l40.355 40.355a17.274 17.274 0 0 0 24.428 0l101.453-101.453c8.402-8.401 22.002-8.404 30.404 0 8.384 8.383 8.384 22.022 0 30.404z" fill="green" stroke="green" stroke-width="50"/> </svg>

结果是一样的,我仍然得到一个空白图像作为输出。

我做错了什么?欢迎任何其他提示。

非常感谢。

【问题讨论】:

  • 该 SVG 包含一个指向其他元素的 use 元素。您还必须对 use 指向的东西进行序列化。
  • 谢谢。我试图通过使用标签序列化符号目标,但我仍然得到一个空白图像,我猜我的代码有问题
  • 嗨@user2360915。在您的最后一个代码(序列化字符串)中,与您想要显示的 SVG 的大小相比,这些值完全不同。您可以回溯一下并发布您首先引用的原始元素(符号、g 或 svg)吗?它的 ID 为 check-green-symbol。然后我们也许可以在此基础上做一个完整的例子。
  • 我在上次编辑中添加了符号
  • @user2360915 我将其包含在我的答案中。

标签: javascript svg canvas png


【解决方案1】:

好的,这是一个包含原始&lt;symbol&gt; 的示例。您可以看到它仅在 &lt;symbol&gt; 是序列化的 SVG 的一部分时才有效(在工作示例中,我将两个类名重命名为“green-check2”和“check-green-symbol2”)。

我稍微重新安排了函数,包括内存中图像的事件侦听器。这里可能不需要它,但在网络上等时是一个很好的做法。

convertSVG(".green-check", "img");
convertSVG(".green-check2", "img2");

function convertSVG(classname, image) {
  var serializer = new XMLSerializer();
  var svgElement = document.querySelector(classname);
  var svgData = new XMLSerializer().serializeToString(svgElement);
  var canvas = document.createElement('canvas');
  var ctx = canvas.getContext("2d");
  var img = new Image;
  img.addEventListener('load', e => {
    canvas.width = e.target.width;
    canvas.height = e.target.height;
    ctx.drawImage(e.target, 0, 0, e.target.width, e.target.height);
    document.getElementById(image).src = canvas.toDataURL();
  });
  img.src = 'data:image/svg+xml;base64,' + btoa(svgData);

}
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
  <symbol id="check-green-symbol" viewBox="0 0 512 512" id=".3539536280039488" xmlns="http://www.w3.org/2000/svg">
    <path d="M437.019 74.981C388.668 26.629 324.38.001 256 .001S123.332 26.629 74.98 74.981C26.629 123.333 0 187.621 0 256.001S26.629 388.669 74.98 437.02C123.332 485.371 187.62 512 256 512c68.381 0 132.668-26.629 181.019-74.98C485.371 388.667 512 324.379 512 255.999s-26.629-132.666-74.981-181.018zM256 477.453C133.891 477.453 34.547 378.11 34.547 256S133.891 34.548 256 34.548s221.453 99.343 221.453 221.453S378.109 477.453 256 477.453z" fill="green" />
    <path d="M393.953 160.709c-21.906-21.904-57.355-21.906-79.264-.001l-89.238 89.239-28.14-28.141c-21.903-21.903-57.354-21.906-79.262 0-21.852 21.852-21.853 57.408 0 79.26l67.772 67.772c10.586 10.586 24.66 16.416 39.631 16.416s29.045-5.83 39.631-16.415l128.87-128.87c21.852-21.851 21.852-57.408 0-79.26zm-24.431 54.832L240.653 344.41c-4.061 4.06-9.459 6.297-15.202 6.297s-11.142-2.237-15.202-6.297l-67.771-67.772c-8.383-8.383-8.383-22.022 0-30.403 8.402-8.401 22-8.404 30.404 0l40.355 40.355a17.274 17.274 0 0 0 24.428 0l101.453-101.453c8.402-8.401 22.002-8.404 30.404 0 8.384 8.383 8.384 22.022 0 30.404z" fill="green" stroke="green" stroke-width="50" />
  </symbol>
</svg>

<p>The original setup (class=green-check):
<svg xmlns="http://www.w3.org/2000/svg" class="green-check" width="24" height="24" role="img" aria-label="moon">
  <use href="#check-green-symbol"/>
</svg>
</p>

<p>The new setup (class=green-check2 and class=check-green-symbol2):
<svg xmlns="http://www.w3.org/2000/svg" class="green-check2" width="24" height="24" role="img" aria-label="moon">
    <symbol id="check-green-symbol2" viewBox="0 0 512 512" id=".3539536280039488" xmlns="http://www.w3.org/2000/svg">
    <path d="M437.019 74.981C388.668 26.629 324.38.001 256 .001S123.332 26.629 74.98 74.981C26.629 123.333 0 187.621 0 256.001S26.629 388.669 74.98 437.02C123.332 485.371 187.62 512 256 512c68.381 0 132.668-26.629 181.019-74.98C485.371 388.667 512 324.379 512 255.999s-26.629-132.666-74.981-181.018zM256 477.453C133.891 477.453 34.547 378.11 34.547 256S133.891 34.548 256 34.548s221.453 99.343 221.453 221.453S378.109 477.453 256 477.453z" fill="green" />
    <path d="M393.953 160.709c-21.906-21.904-57.355-21.906-79.264-.001l-89.238 89.239-28.14-28.141c-21.903-21.903-57.354-21.906-79.262 0-21.852 21.852-21.853 57.408 0 79.26l67.772 67.772c10.586 10.586 24.66 16.416 39.631 16.416s29.045-5.83 39.631-16.415l128.87-128.87c21.852-21.851 21.852-57.408 0-79.26zm-24.431 54.832L240.653 344.41c-4.061 4.06-9.459 6.297-15.202 6.297s-11.142-2.237-15.202-6.297l-67.771-67.772c-8.383-8.383-8.383-22.022 0-30.403 8.402-8.401 22-8.404 30.404 0l40.355 40.355a17.274 17.274 0 0 0 24.428 0l101.453-101.453c8.402-8.401 22.002-8.404 30.404 0 8.384 8.383 8.384 22.022 0 30.404z" fill="green" stroke="green" stroke-width="50" />
  </symbol>
  <use href="#check-green-symbol2"/>
</svg>
</p>

<p>The original output (blank image): <img id="img" /></p>

<p>The new output (including serialized symbol): <img id="img2" /></p>

【讨论】:

  • 谢谢。这很烦人,将符号放在外面可以避免到处复制数据。
  • @user2360915 确实如此,但与此同时,PNG 图像也是一个独立的单元。
猜你喜欢
  • 2017-03-23
  • 2015-12-27
  • 2019-01-19
  • 2014-05-04
  • 2017-03-03
  • 2014-04-01
  • 2019-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多