Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using css in converted svg to img

Tags:

I am trying to convert an svg to an image format. Actually a lot works very fine and I know how to convert from SVG to canvas and from canvas to img. My problem is that the svg uses css that has been included as css file and by converting to canvas, the styles will be lost.

Does anyone has an idea how to copy the styles into my svg or canvas?

Here is my code: https://jsfiddle.net/DaWa/70w9db1d/

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>SVG2IMG</title>
    <link rel="stylesheet" href="./circle.css">
</head>
<body>
<svg width="100" height="100">
    <circle cx="50" cy="50" r="40"/>
</svg>

<script>
  var svg = document.querySelector('svg');

  let xml  = new XMLSerializer().serializeToString(svg);
  let data = "data:image/svg+xml;base64," + btoa(xml);
  let img  = new Image();
  img.src  = data;
  document.body.appendChild(img)

</script>

</body>
</html>

And my css:

circle {
    fill:red
}
like image 842
user7521838 Avatar asked Jul 07 '17 07:07

user7521838


1 Answers

I used this trick to add computed style of each node to its style attribute, and it works. may be it can help you.

Update 1: some browsers do not support the cssText property so you can use the code below which is a bit more cross browser.

Update 2: Firefox computes css quotes property which include some invalid string chars that btoa can not encode properly.

let addStyle = function(children) {
   for (let i = 0; i < children.length; i++) {
     let child = children[i];
     if (child instanceof Element) {
       let cssText = '';
       let computedStyle = window.getComputedStyle(child, null);
       for (let i = 0; i < computedStyle.length; i++) {
         let prop = computedStyle[i];
         cssText += prop + ':' + computedStyle.getPropertyValue(prop) + ';';
       }
       child.setAttribute('style', cssText);
       addStyle(child.childNodes);
     }
   }
 }

 let svg = document.querySelector('svg');
 addStyle(svg.childNodes);
 let xml = new XMLSerializer().serializeToString(svg);
 let data = "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(xml)));
 let img = new Image();
 img.src = data;
 document.body.appendChild(img);
circle {
  fill: red
}
<svg width="100" height="100">
  <circle cx="50" cy="50" r="40" />
</svg>
like image 124
Nima Hakimi Avatar answered Oct 14 '22 22:10

Nima Hakimi