Skip to content
Advertisement

Load SVG into canvas to get base64 dataurl

I have this SVG in my html :

<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>

the symbol pointed by the “use” tag is :

<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>

This display correctly when the page load (ie. it is using the symbol that I refer to using use tag).

I want to take this SVG and get the base64 dataurl (convert it to an image).

I tried to use this code without success, it always gets me a white/blank image.

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();
}

The base64 I get in the console looks like this :

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

I also tried to serialize the element pointed by the “use” tag as per “Robert Longson” suggested, with this part of code :

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);

The serialized string looks like this :

<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>

The result is the same, I still get a blank image as output.

What am I doing wrong? Any other hint is welcome.

Thanks a lot.

Advertisement

Answer

OK, here is an example that includes the original <symbol>. You can see that it only works when the <symbol> is part of the SVG that is serialized (in the working example I renamed the two class names to “green-check2” and “check-green-symbol2”).

I rearanged the function a bit, including an event listener for the in-memory-image. It is probably not needed here, but a good practice when on a network etc.

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>
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement