Reputation: 415
Is there a way to contour or outline a svg element with SnapSVG ot other JavaScript Lib?
Upvotes: 0
Views: 1823
Reputation: 54089
Create a canvas slightly bigger than the SVG size you want.
Draw a rectangle over it in the colour you want the outLine. Set globalCompositeOperation = "destination-atop"
then draw the SVG on top. Now you have a mask of the SVG.
Then draw that Mask on another canvas in a circle the with the radius you want the outline. Then draw the SVG on top and you have an outlined SVG.
If you have semi transparent parts you will have to do some extra work. But that's the general principle.
// the SVG image to outline
svg = `<?xml version="1.0"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="328" height="208" id="testSVG" ><defs></defs><path d="M278.5,30Q317.3,35.8,319,72.5Q288.3,93.3,262.5,65Q242.8,77.3,252,134.5Q261.3,160.3,283.5,149C317.8,121.6,257.5,130.8,271,98.5Q270.9,95.6,319.5,97Q322.4,96.9,321,160.5Q297.8,189.3,261.5,185Q237.3,181.3,226,156.5Q214,135.5,218,86.5Q227.8,44.8,242.5,38Q264.5,26,278.5,30Z
M42.5,30Q89.3,27.3,93,67.5C63.5,99,51.5,42,38,67.5Q95.5,95,97,126.5Q99.3,175.3,60.5,185Q32,187,21.5,177Q4.8,157.3,5,142.5C34.9,102.2,48.5,175.5,65,145.5C75.9,118.3,8.4,111.6,9,86.5Q4.3,36.8,42.5,30Z
M102.5,33Q133.5,33,135,33.5L157,136L179,33.5Q179,32.5,211,33.5Q173.8,191.3,173.5,182Q139,182.5,139,181.5Q99.9,33.6,102.5,33Z
" fill="rgba(255,134,0,1.000)" fill-rule="evenodd" stroke="transparent" stroke-width="1" stroke-opacity="1" ></path></svg>`
// creates image with 2dContext attached
var createImage= function(w,h){
var image = document.createElement("canvas");
image.width = w;
image.height =h;
image.ctx = image.getContext("2d");
return image;
}
// Setting width is in pixels
var outlineWidth = 8;
var outlineColour = "Yellow";
// Function to outline SVG image. Or any image
function outline(){ // as this is the onload this is the image to outline
var w = this.width + outlineWidth*2+2; // get the new width and height
var h = this.height + outlineWidth*2+2;
var mask = createImage(w,h); // create the mask image
mask.ctx.clearRect(0,0,w,h); // Clear is You must do this for destination-atop to work
mask.ctx.fillStyle = outlineColour; //
mask.ctx.fillRect(0,0,w,h); // fill the image with the outline colour
mask.ctx.globalCompositeOperation = "destination-atop"; // now set so only pixels drawn on will show background colour
mask.ctx.drawImage(this,outlineWidth+1,outlineWidth+1);
// we now have a mask of the SVG in the colour we want
var outlined = createImage(w,h); // create the final image
// draw an outline by drawing a circle with the mask
for(var i = 0; i < Math.PI*2; i+= (Math.PI*2)/(outlineWidth*2)){
var x = Math.cos(i)*outlineWidth+outlineWidth+1;
var y = Math.sin(i)*outlineWidth+outlineWidth+1;
outlined.ctx.drawImage(mask,x,y);
}
// draw the SVG in the center of the outline
outlined.ctx.drawImage(this,outlineWidth*2+1,outlineWidth*2+1);
// done so show the world
var output = document.getElementById("resultImage");
output.src = outlined.toDataURL();
}
var svgImage = new Image();
svgImage.onload = outline;
svgImage.src = "data:image/svg+xml;base64,"+btoa(svg);
var input = document.getElementById("inImg");
input.src = "data:image/svg+xml;base64,"+btoa(svg);
SVG outlined<br>Outlined image will appear below the original<br>
<img id="inImg">
<img id="resultImage">
Upvotes: 1