Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change svg fill color and then draw to canvas

What I want to do is load an svg, change its fill color to a random value and then draw it on the canvas. This has proved to be much more difficult than I would have thought. Here's the code I have at the moment.

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

//images
var bottomLeftTop = new Image();
var bottomRightTop = new Image();
var fullTop= new Image();
var leftMidSide = new Image();
var leftSide = new Image();
var rightMidSide = new Image();
var rightSide = new Image();
var topLeftTop = new Image();
var topRightTop = new Image();

bottomLeftTop.src = "img/bottomLeftTop.svg";
bottomRightTop.src = "img/bottomRightTop.svg";
fullTop.src = "img/fullTop.svg";
leftMidSide.src = "img/leftMidSide.svg";
leftSide.src = "img/leftSide.svg";
rightMidSide.src = "img/rightMidSide.svg";
rightSide.src = "img/rightSide.svg";
topLeftTop.src = "img/topLeftTop.svg";
topRightTop.src = "img/topRightTop.svg";

//draw
context.drawImage(fullTop,50,50);

I'm currently loading my svg's as Image objects, which works fine for just drawing but won't allow me to change the fill color.

I did try converting my svg to canvas commands, which allows me to change the fill but requires a lot of work to get scaled and positioned properly, and just isn't feasible with the amount of images I'm working with.

Is there any other way I can do this while still working with the canvas?

like image 829
thrillingheroics Avatar asked Dec 22 '14 04:12

thrillingheroics


People also ask

Can I draw SVG in canvas?

Complete HTML/CSS Course 2022To draw SVG onto canvas, you need to use SVG image. Firstly, use the <foreignObject> element which contains the HTML. After that, you need to draw the SVG image into the canvas.


1 Answers

The trick is to load your svg as XML via XHR and manipulate it any way you want, then create your image out of it using data:image format.

E.g.

$.get('img/bottomLeftTop.svg', function(svgXml) {
  var img = new Image();
  var coloredSvgXml = svgXml.replace(/#3080d0/g,'#e05030');
  img.src = "data:image/svg+xml;charset=utf-8,"+coloredSvgXml;
  context.drawImage(img,0,0);
});

Here is a snippet I created to demonstrate the manipulation principle. It uses in-html hidden svg node to draw on 2d canvas, then changes the color via regexp and draws on the same canvas again:

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");



var svg = document.getElementById('tmpSvg')
var blueCircle = (new XMLSerializer).serializeToString(svg);
var img = new Image();
img.src = "data:image/svg+xml;charset=utf-8," + blueCircle;
context.drawImage(img, 0, 0);

redCircle = blueCircle.replace(/#3080d0/g, '#e05030');
img = new Image();
img.src = "data:image/svg+xml;charset=utf-8," + redCircle;
context.drawImage(img, 10, 10);
.wrapper {
  display: none;
}
#canvas {
  width: 400px;
  height: 300px;
}
<canvas id="canvas"></canvas>

<div class="wrapper">
  <svg id="tmpSvg" version="1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200">
    <style>
      circle {
        fill-opacity: 0.5;
        stroke-width: 4;
        fill: #3080d0;
        stroke: #3080d0;
      }
    </style>
    <circle id="my-circle" cx="50" cy="50" r="30" />
  </svg>
</div>

Of course, nothing prevents you from using JavaScript built-in XML parser and XPath-based node manipulation. But in this particular case and for particular colors, regexp is probably more efficient.

like image 146
Alex Pakka Avatar answered Nov 15 '22 13:11

Alex Pakka