Reputation: 86
I tried to create border for image in svg like this :
<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1054 670" xml:space="preserve">
<defs>
<filter id="f3" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceAlpha" dx="0" dy="1"></feOffset>
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="0.5"></feGaussianBlur>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"></feBlend>
</filter>
</defs>
<image overflow="visible" x="5" width="200" height="300" filter="url(#f3)" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://upload.wikimedia.org/wikipedia/commons/9/9e/Flag_of_Japan.svg" >
</image>
</svg>
but it just a border-bottom. How can i add border top right and left. Thanks you
Upvotes: 1
Views: 2239
Reputation: 101800
You are only getting the bottom border because you only have a single <feOffset>
in your filter that does a shift down of the SourceAlpha. Hence only the bottom border.
If you want to stick to using filters, then you can just use four <feOffset>
elements so you get all four borders. In the following example I am actually shifting the offsets in the direction of each corner so that you don't get missing corner pixels.
<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1054 670" xml:space="preserve">
<defs>
<filter id="f3">
<feOffset result="nw" in="SourceAlpha" dx="-3" dy="-3"></feOffset>
<feOffset result="ne" in="SourceAlpha" dx="3" dy="-3"></feOffset>
<feOffset result="se" in="SourceAlpha" dx="3" dy="3"></feOffset>
<feOffset result="sw" in="SourceAlpha" dx="-3" dy="3"></feOffset>
<feMerge>
<feMergeNode in="nw"/>
<feMergeNode in="ne"/>
<feMergeNode in="se"/>
<feMergeNode in="sw"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<image overflow="visible" x="5" width="200" height="300" filter="url(#f3)" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://upload.wikimedia.org/wikipedia/commons/9/9e/Flag_of_Japan.svg" >
</image>
</svg>
The four corner-shifted SourceAlphas provide the black border. Then we merge the original image on top.
Update: How to change border colour
To make the border colour something other than black, we have to add some more operations to the filter. The simplest way is to fill the filter area with the new border colour, then mask it against the black border rectangle. Once that is done, we can merge the flag image on top as before.
<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1054 670" xml:space="preserve">
<defs>
<filter id="f3">
<!-- Make four copies of the image alpha, each moved to a different corner -->
<feOffset result="nw" in="SourceAlpha" dx="-3" dy="-3"></feOffset>
<feOffset result="ne" in="SourceAlpha" dx="3" dy="-3"></feOffset>
<feOffset result="se" in="SourceAlpha" dx="3" dy="3"></feOffset>
<feOffset result="sw" in="SourceAlpha" dx="-3" dy="3"></feOffset>
<!-- Merge those four copies together -->
<feMerge result="blackborder">
<feMergeNode in="nw"/>
<feMergeNode in="ne"/>
<feMergeNode in="se"/>
<feMergeNode in="sw"/>
</feMerge>
<!-- Create a filter primitive that is just a solid block of what will be
the new border colour (in this case orange) -->
<feFlood flood-color="orange"/>
<!-- Use the "in" operator to merge the blackborder with the orange fill.
Any parts of the orange fill that are "in"-side the back shape will remain.
The rest will me masked out. -->
<feComposite in2="blackborder" operator="in" />
<!-- Finally, merge the new orange border with the original image -->
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<image overflow="visible" x="5" y="5" width="200" height="300" filter="url(#f3)" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://upload.wikimedia.org/wikipedia/commons/9/9e/Flag_of_Japan.svg" >
</image>
</svg>
Upvotes: 1
Reputation: 46
2 options:
1- resize the SVG element to match the image and use CSS border
2- draw a rect around your image
option2 jsfiddle demo:
UPDATE: Programmatically adding a rect as a border to your image using javascript, with resize and border color change functions:
function addBorders(image){
var x = image.getAttribute("x");
x = x ? x : 0;
var y = image.getAttribute("y");
y = y ? y : 0;
var w = image.getAttribute("width");
var h = image.getAttribute("height");
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
rect.setAttribute("style","fill:white; fill-opacity:0;stroke:black; stroke-width:2px;");
rect.id = image.id + "rect";
console.log(rect.id);
rect.setAttribute("x",x);
rect.setAttribute("y",y);
rect.setAttribute("width",w);
rect.setAttribute("height",h);
var parent = image.parentNode;
parent.insertBefore(g,image);
g.appendChild(image);
g.insertBefore(rect,image.nextSibling);
}
function redrawBorder(rect,w,h){
rect.setAttribute("width",w);
rect.setAttribute("height",h);
}
window.updatePosition = function(image,x,y){
document.getElementById(image.id + "rect")
image.setAttribute("x",x);
image.setAttribute("y",y);
moveBorder(image.nextSibling,x,y);
}
function moveBorder(rect,x,y){
rect.setAttribute("x",x);
rect.setAttribute("y",y);
}
window.updateSize = function(image,w,h){
document.getElementById(image.id + "rect")
image.setAttribute("width",w);
image.setAttribute("height",h);
redrawBorder(image.nextSibling,w,h);
}
window.updateColor = function(image,color){
document.getElementById(image.id + "rect").style.stroke=color;
}
var image = document.getElementById("image1");
addBorders(image);
Demo: jsfiddle
Upvotes: 0