Dynamic svg width/height after applying a stroke - svg

I made an svg with a masked image and applied a stroke to the mask:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="100%" height="100%">
<defs>
<g id="path">
<path fill="#ffffff"
d="m380.42 600l -235.11 123.61 44.9 -261.8 -190.21 -185.41 262.87 -38.2 117.56 -238.2 117.56 238.2 262.87 38.2 -190.21 185.41 44.9 261.8 z"/>
</g>
<mask id="image-mask">
<use xlink:href="#path" overflow="visible"/>
</mask>
</defs>
<use xlink:href="#path" overflow="visible" stroke="red" stroke-width="20"/>
<image width="781" height="744" xlink:href="cat3.jpg" mask="url(#image-mask)"/>
</svg>
Unfortunately parts of the stroke get cut off and the result is this:
The top/left part of the border are cut off.
Is there any way to make them visible without modifying the width/height and viewBox by hand?

Like others have said, you could translate the path away from the edge of the SVG. Another option would be to use this technique using clipPath to bring your stroke lines 'inside' the shape rather than outside which is what is causing the lines to be clipped off the edge of the drawing (based on this answer):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="781px" height="744px">
<defs>
<path fill-opacity="0" id="path"
d="m380.42 600l -235.11 123.61 44.9 -261.8 -190.21 -185.41 262.87 -38.2 117.56 -238.2 117.56 238.2 262.87 38.2 -190.21 185.41 44.9 261.8 z"></path>
<clipPath id="clip">
<use xlink:href="#path" />
</clipPath>
</defs>
<image width="781" height="744" xlink:href="cat3.jpg" clip-path="url(#clip)"/>
<use xlink:href="#path" stroke="red" stroke-width="20" clip-path="url(#clip)"/>
</svg>
Also, note that I've brought the image element before use so that the stroke lines are drawn over the image, and applied fill-opacity="0" to the path so the image can be seen through the shape.

Related

Clip Path not working in an SVG element

I'm trying to get a rectangular <clipPath> to clip a <circle> in an SVG element, but I can't seem to get it work.
Does anyone know what the problem is?
Many thanks in advance for any help.
Codepen: https://codepen.io/emilychews/pen/jpLMaV
Em
#circle {width: 10rem;}
<defs>
<clipPath id="myClipPath">
<rect x="30" y="30" width="100" height="100"/>
</clipPath>
</defs>
<svg id="circle" style="clip-path: url(#myClipPath)" viewBox="0 0 391 391">
<circle fill="#000" cx="195.5" cy="195.5" r="195"/>
</svg>
You forget <svg> around your clip path declaration .
<svg width=0 height=0 >
<defs>
<clipPath id="myClipPath">
<rect x="50px" y="50px" width="200px" height="200px"/>
</clipPath>
</defs>
</svg>
<svg style="clip-path: url(#myClipPath)" id="circle" width="400" height="400">
<circle fill="#000" cx="100px" cy="100px" r="100px"/> </svg>
edit: i simplified and i added a witdh and height attribute

Flatten clipped areas in SVG to transparency?

I have this SVG file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<g id="main">
<clipPath id="clip_mask">
<path d="M20.9262,32C18.5189,30.6,16.9,27.9878,16.9,25c0,-4.4735,3.6265,-8.1,8.1,-8.1c2.9878,0,5.6,1.6189,7,4.0262V0L0,0l0,32H20.9262z" fill-rule="evenodd"/>
</clipPath>
<g id="icon" clip-path="url(#clip_mask)">
<g id="transformed_icon" transform="translate(-1 -1)">
<path d="M26.7,30.5H5.3c-0.4418,0,-0.8,-0.3582,-0.8,-0.8V2.3c0,-0.4418,0.3582,-0.8,0.8,-0.8h21.4c0.4418,0,0.8,0.3582,0.8,0.8v27.4C27.5,30.1418,27.1418,30.5,26.7,30.5z" fill="#FFFFFF" stroke="#6D6E71" stroke-width="1" stroke-miterlimit="1"/>
<path d="M8.5,8.5h15M8.5,11.5h15M8.5,14.5h15M8.5,17.5h15M8.5,20.5h15M8.5,23.5h15" fill="none" stroke="#3E79B4" stroke-width="1" stroke-linecap="round" stroke-miterlimit="1"/>
</g>
</g>
<g id="overlay">
<path d="M25,18c-3.866,0,-7,3.134,-7,7c0,3.866,3.134,7,7,7s7,-3.134,7,-7C32,21.134,28.866,18,25,18zM26,29.8c0,0.1105,-0.0895,0.2,-0.2,0.2h-1.6c-0.1105,0,-0.2,-0.0895,-0.2,-0.2v-6.6c0,-0.1105,0.0895,-0.2,0.2,-0.2h1.6c0.1105,0,0.2,0.0895,0.2,0.2V29.8zM26,21.5c0,0.1105,-0.0895,0.2,-0.2,0.2h-1.6c-0.1105,0,-0.2,-0.0895,-0.2,-0.2v-1.3c0,-0.1105,0.0895,-0.2,0.2,-0.2h1.6c0.1105,0,0.2,0.0895,0.2,0.2V21.5z" fill-rule="evenodd" fill="#3E79B4"/>
<path d="M26,20.2c0,-0.1105,-0.0895,-0.2,-0.2,-0.2h-1.6c-0.1105,0,-0.2,0.0895,-0.2,0.2v1.3c0,0.1105,0.0895,0.2,0.2,0.2h1.6c0.1105,0,0.2,-0.0895,0.2,-0.2V20.2z" fill="#FFFFFF"/>
<path d="M26,23.2c0,-0.1105,-0.0895,-0.2,-0.2,-0.2h-1.6c-0.1105,0,-0.2,0.0895,-0.2,0.2v6.6c0,0.1105,0.0895,0.2,0.2,0.2h1.6c0.1105,0,0.2,-0.0895,0.2,-0.2V23.2z" fill="#FFFFFF"/>
</g>
</g>
</svg>
It is an icon with an overlay in the bottom-right corner. There is a clip-gap between the main icon area and the overlay area. This clip-gap is displayed correctly in Affinity Designer 1.5.3.69:
But unfortunately, many other programs don't recognize the clip-gap, so they don't display it. For example, here is a screenshot from LibreOffice Draw:
So, is it possible to "flatten" the clipped area in the SVG to the same background transparency as the icon background? This would make the SVG clip-gap visible and transparent in such incompatible programs and would allow programs which don't support clipped areas in SVG to render the clipped area as transparency.
I've found a practical but cumbersome and time-consuming solution: Since the SVG is displayed correctly in Affinity Designer, I print the SVG in Affinity Designer to a PDF printer driver. Then I reimport the PDF in Affinity Designer and export it as SVG. Then I can import the SVG in a renderer which doesn't support clipping and it is rendered perfectly. It works.
Yes it is possible to re-use a clip shape to make the clipped area transparent using a filter. However, I very much doubt that a renderer that can't handle clipping properly will be able to handle a filter. But here's how you would do that:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="32px" height="32px" viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<defs>
<clipPath id="clip_mask">
<path id="original-clip-shape" d="M20.9262,32C18.5189,30.6,16.9,27.9878,16.9,25c0,-4.4735,3.6265,-8.1,8.1,-8.1c2.9878,0,5.6,1.6189,7,4.0262V0L0,0l0,32H20.9262z" fill-rule="evenodd"/>
</clipPath>
<filter id="transparentize">
<feImage xlink:href="#original-clip-shape" x="0" y="0"/>
<feComposite operator="in" in="SourceGraphic"/>
</filter>
</defs>
<g id="main">
<g id="icon" clip-path="url(#clip_mask)">
<g id="filter-layer" filter="url(#transparentize)">
<g id="transformed_icon" transform="translate(-1 -1)">
<path d="M26.7,30.5H5.3c-0.4418,0,-0.8,-0.3582,-0.8,-0.8V2.3c0,-0.4418,0.3582,-0.8,0.8,-0.8h21.4c0.4418,0,0.8,0.3582,0.8,0.8v27.4C27.5,30.1418,27.1418,30.5,26.7,30.5z" fill="#FFFFFF" stroke="#6D6E71" stroke-width="1" stroke-miterlimit="1"/>
<path d="M8.5,8.5h15M8.5,11.5h15M8.5,14.5h15M8.5,17.5h15M8.5,20.5h15M8.5,23.5h15" fill="none" stroke="#3E79B4" stroke-width="1" stroke-linecap="round" stroke-miterlimit="1"/>
</g>
</g>
</g>
<g id="overlay">
<path d="M25,18c-3.866,0,-7,3.134,-7,7c0,3.866,3.134,7,7,7s7,-3.134,7,-7C32,21.134,28.866,18,25,18zM26,29.8c0,0.1105,-0.0895,0.2,-0.2,0.2h-1.6c-0.1105,0,-0.2,-0.0895,-0.2,-0.2v-6.6c0,-0.1105,0.0895,-0.2,0.2,-0.2h1.6c0.1105,0,0.2,0.0895,0.2,0.2V29.8zM26,21.5c0,0.1105,-0.0895,0.2,-0.2,0.2h-1.6c-0.1105,0,-0.2,-0.0895,-0.2,-0.2v-1.3c0,-0.1105,0.0895,-0.2,0.2,-0.2h1.6c0.1105,0,0.2,0.0895,0.2,0.2V21.5z" fill-rule="evenodd" fill="#3E79B4"/>
<path d="M26,20.2c0,-0.1105,-0.0895,-0.2,-0.2,-0.2h-1.6c-0.1105,0,-0.2,0.0895,-0.2,0.2v1.3c0,0.1105,0.0895,0.2,0.2,0.2h1.6c0.1105,0,0.2,-0.0895,0.2,-0.2V20.2z" fill="#FFFFFF"/>
<path d="M26,23.2c0,-0.1105,-0.0895,-0.2,-0.2,-0.2h-1.6c-0.1105,0,-0.2,0.0895,-0.2,0.2v6.6c0,0.1105,0.0895,0.2,0.2,0.2h1.6c0.1105,0,0.2,-0.0895,0.2,-0.2V23.2z" fill="#FFFFFF"/>
</g>
</g>
</svg>
As far as workarounds go, it's hard to debug renderer specific problems without the renderer. But here are some thoughts:
It might support clipping but just not support using the stroke as a clip. You could work around this by using a solid circle as the clip-shape.
it might support masking not clipping. In this case, define a mask that's the inverse of the clip and apply that.
it might not support clipping or masking at all. In that case, you'll have to just draw the original content as if it was being clipped using markers to shape the ends of your paths. (ugh!)

How must this SVG file change to allow FileMaker to alter its color?

I have an SVG file generated by Sketch that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<svg width="72px" height="47px" viewBox="0 0 72 47" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none"
fill-rule="evenodd" stroke-linecap="square">
<g id="Group" transform="translate(4.000000, 3.000000)"
stroke="#000000" stroke-width="9">
<path d="M0.5,39.5 L63.5,39.5" id="Line"></path>
<path d="M0.5,20.5 L63.5,20.5" id="Line-Copy"></path>
<path d="M0.5,1.5 L63.5,1.5" id="Line-Copy-2"></path>
</g>
</g>
</svg>
I'm trying to edit it in a text editor so that when I import it as an icon button, it can be colored by FileMaker.
I have repeatedly read that adding class="fm_fill" is what's required. I've tried adding this to the outside <g> tag, the inside <g> tag and to each of the <path> tags. I've tried removing superfluous attributes, such as the outside <g> tag's stroke and stroke-width attributes. I've tried consolidating the <g> tags and changing the fill attribute in the outside <g> tag. I've also tried removing the <path> id attributes and using self-closing <path> tags.
My test is a simple button with an icon that I first color. Then I add the edited SVG and see if it retains the color. So far I haven't been able to get it to do so.
Assuming you want the horizontal bars to be colored in FileMaker, you need to convert the stroke to a filled path or a rect.
Something like this:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="72px" height="47px" viewBox="0 0 72 47" overflow="inherit" xml:space="preserve">
<title>Group</title>
<desc>Created with Sketch.</desc>
<g id="Page-1">
<g id="Group" transform="translate(4.000000, 3.000000)">
<rect x="-4" y="35" width="72" height="9"/>
<rect x="-4" y="16" width="72" height="9"/>
<rect x="-4" y="-3" width="72" height="9"/>
</g>
</g>
</svg>
You dont "need" to add the class="fm_fill" per se, but adding a raw SVG does not show the icon in the icon selector, just a blank entry.
If you add the class="fm_fill" and a default fill color, you will see the icon in the icon selector in the default fill color, making it much easier to work with.
Like this:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" width="72px" height="47px" viewBox="0 0 72 47" overflow="inherit" xml:space="preserve">
<title>Group</title>
<desc>Created with Sketch.</desc>
<g id="Page-1">
<g id="Group" class="fm_fill" fill="grey" transform="translate(4.000000, 3.000000)">
<rect x="-4" y="35" width="72" height="9"/>
<rect x="-4" y="16" width="72" height="9"/>
<rect x="-4" y="-3" width="72" height="9"/>
</g>
</g>
</svg>
In the following screenshot, you can see both variants. The left blue icon is just your raw converted icon, then colored blue in FileMaker. It is not visible in the icon selector, it is the blank entry next to the selected icon. The selected red button's icon is colored red in FileMaker and has the class and default fill applied and thus is visible in the icon selector.
Hope this helps.

svg changes when converted to symbol

I have this dummy svg showing a cirle with some grey figure inside
<svg viewBox="0 0 86 86" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<circle id="path-1" cx="43" cy="43" r="43"></circle>
</defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g transform="translate(-585.000000, -391.000000)">
<g transform="translate(585.000000, 391.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<use id="Oval" fill="currentcolor" xlink:href="#path-1"></use>
<g id="Group" mask="url(#mask-2)" fill="#b8b8b8">
<g transform="translate(21.500000, 27.823529)" id="Page-1">
<path d="M0.5,0.176470588 L0.5,58.1764706 L15.5,58.1764706 L15.5,49.1764706 L29.5,49.1764706 L29.5,31.1764706 L7.5,31.1764706 L7.5,37.1764706 Z"></path>
</g>
</g>
</g>
</g>
</g>
when I convert it to a sprite using gulp-svg-sprite with mode symbol I get this result
<?xml version="1.0" encoding="UTF-8" ?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><symbol viewBox="0 0 86 86" id="company"><defs><circle id="aa" cx="43" cy="43" r="43"/></defs><g fill="none" fill-rule="evenodd"><mask id="ab" fill="#fff"><use xlink:href="#aa"/></mask><use fill="currentcolor" xlink:href="#aa"/><g mask="url(#ab)" fill="#b8b8b8"><path d="M22 28v58h15v-9h14V59H29v6z"/></g></g></symbol></svg>
Now the grey figure breaks out of the circle and this even happens if I copy root defs- and g-tags from my original svg directly into the symbol-tag. I have also tried inserting a clipPath in the symbol version but with no luck.
What am I missing here?
UPDATED: Simplifying your svg may work ... try with the examples below, one using symbols, one without (in case the gulp sprite code cannot have nested symbols) ... it may be an issue with the defs area.
svg {
width: 100px;
}
<svg viewBox="0 0 86 86" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="c">
<circle cx="43" cy="43" r="43" fill="currentColor" />
</symbol>
<mask id="mask" color="#fff">
<use xlink:href="#c" />
</mask>
</defs>
<use xlink:href="#c" color="#666" />
<path fill="#999" mask="url(#mask)" d="M10 0v60h30v-10h20v-20h-30v9z" />
</svg>
<svg viewBox="0 0 86 86" xmlns="http://www.w3.org/2000/svg">
<defs>
<mask id="mask2" color="#fff">
<circle cx="43" cy="43" r="43" fill="#FFF" />
</mask>
</defs>
<circle cx="43" cy="43" r="43" fill="currentColor" />
<path fill="#999" mask="url(#mask2)" d="M10 0v60h30v-10h20v-20h-30v9z" />
</svg>
It is probably not a complete answer but I managed to get it work;
First I extended my defs with a clipPath using my circle
<defs>
<circle id="circle" cx="43" cy="43" r="43"></circle>
<clipPath id="clippath"><use overflow="visible" xlink:href="#circle" /></clipPath>
</defs>
Then, using the clipPath on my first group and switching from gulp-svg-sprite to gulp-svgstore (which moves the defs to the top, above the symbols) gives me what I expect both as single svg and as an svg symbol sprite.

Grouping several SVG's into one object

I'm trying to reuse an SVG sprite icone into new SVG object.
The new object is just a circle that contains the icon from the sprite.
I understand that I need to use the defs tag to group some shapes together,
But i have have a problem referencing my sprite icone inside the defs tag.
sprite:
<svg style="display:none;">
<symbol id="icon_1" viewBox="0 0 54 54">
<path d="M10.6 29.3h14.5V44H10.6z" class="st0"/>
<path d="M25 29.3h14.5V44H25zm-7.2-14.7h14.5v14.7H17.8zm0 0l3.9-4m10.6 4l3.9-4m-3.9 18l3.9-3.7m-25.6 4.4l4.3-4.4m24.6 4.7l3.9-4M39.5 44l3.9-4M21.2 10.6h15M14.5 24.9h3.3m17.7.6h7.9M36.2 10v15.5m7.2.1V40" class="st0"/>
</symbol >
new object:
<svg><defs>
<g id="shape">
<circle cx="40" cy="40" r="40" fill="rgba(124,240,10,0.5)" />
<image x="0" y="0" xlink:href="#icon_1"></image>
</g>
I read that i can use image tags to reference SVG elements.
obviously i'm doing something wrong.
Basically the expected result should be a stroked circle with the icon inside
in a way that I will be able to animate the entire object
Thanks
You were close. Your main problem was that you were careless with your opening and closing tags.
Your second SVG had a stray opening <defs> element, which meant that the <g id="shape"> element was left inside the <defs> section. <defs> is for defining elements to be re-used later, and anything in a <defs> will only be drawn when referenced from elsewhere.
There were a couple of other problems.
You can't use an <image> to reference a symbol. You will need to use a <use> for that.
You will need to supply a width and height so that the symbol gets draw at an appropriate size.
<svg width="0" height="0">
<defs>
<symbol id="icon_1" viewBox="0 0 54 54">
<path d="M10.6 29.3h14.5V44H10.6z" class="st0"/>
<path d="M25 29.3h14.5V44H25zm-7.2-14.7h14.5v14.7H17.8zm0 0l3.9-4m10.6 4l3.9-4m-3.9 18l3.9-3.7m-25.6 4.4l4.3-4.4m24.6 4.7l3.9-4M39.5 44l3.9-4M21.2 10.6h15M14.5 24.9h3.3m17.7.6h7.9M36.2 10v15.5m7.2.1V40" class="st0"/>
</symbol>
</defs>
</svg>
new object:
<svg>
<g id="shape">
<circle cx="40" cy="40" r="40" fill="rgba(124,240,10,0.5)" />
<use x="0" y="0" width="80" height="80" xlink:href="#icon_1"></use>
</g>
</svg>
The image tag is designed to be used with complete images, not fractions. I guess that use is the right tag for your use case.
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1">
<symbol id="icon_1" viewBox="0 0 54 54">
<path d="M10.6 29.3h14.5V44H10.6z" class="st0"/>
<path d="M25 29.3h14.5V44H25zm-7.2-14.7h14.5v14.7H17.8zm0 0l3.9-4m10.6 4l3.9-4m-3.9 18l3.9-3.7m-25.6 4.4l4.3-4.4m24.6 4.7l3.9-4M39.5 44l3.9-4M21.2 10.6h15M14.5 24.9h3.3m17.7.6h7.9M36.2 10v15.5m7.2.1V40" class="st0"/>
</symbol>
<defs>
<g id="shape">
<circle cx="40" cy="40" r="40" fill="rgba(124,240,10,0.5)" />
<use x="2" y="-3" width="80" height="80" xlink:href="#icon_1"/>
</g>
</defs>
<use xlink:href="#shape"/>
</svg>
Also, if the sprite is in a separate file, you have to reference the symbol within that file: <use hlink:href="sprites.svg#icon1"/>.

Resources