SVG file only works in certain places - svg

I have a very simple svg file, a book shelf, which I extracted from a public domain image in Inkscape.
My intention is to use an SVG Renderer within WinForms to produce bitmaps of variable widths from it.
It works fine within Inkscape but doesn't want to display in IE or Chrome or the DevExpress Svg renderer or a public domain SVG Viewer.
What should I change in the XML to make it work outside Inkscape?
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg11134"
version="1.1"
viewBox="0 0 100 9.9999993"
height="10mm"
width="100mm">
<defs
id="defs11128">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath304">
<path
d="M 4410,3710 H 90 v -180 h 4320 z"
id="path302" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath320">
<path
d="M 360,3890 90,3710 h 4320 l -270,180 z"
id="path318" />
</clipPath>
<linearGradient
x1="0"
y1="0"
x2="1"
y2="0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-7.9e-6,180,180,7.9e-6,2250,3710)"
spreadMethod="pad"
id="linearGradient326">
<stop
style="stop-opacity:1;stop-color:#ebecea"
offset="0"
id="stop322" />
<stop
style="stop-opacity:1;stop-color:#d6d7d5"
offset="1"
id="stop324" />
</linearGradient>
</defs>
<g
transform="translate(13.396613,-100.26342)"
id="layer1">
<g
id="g9848"
transform="matrix(-0.62409419,0,0,0.93340311,-15.02437,93.369296)">
<g
transform="matrix(0.02909742,0,0,-0.02975968,4.8287909,123.15116)"
id="g9840">
<g
id="g9838"
>
<path
d="M 4410,3710 H 90 v -180 h 4320 v 180"
style="fill:#d6d7d5;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path9836" />
</g>
</g>
<g
transform="matrix(0.02909742,0,0,-0.02975968,4.8287909,123.15116)"
id="g9846">
<g
id="g9844"
>
<path
d="M 360,3890 90,3710 h 4320 l -270,180 H 360"
style="fill:url(#linearGradient326);fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path9842" />
</g>
</g>
</g>
</g>
</svg>

The grafics were outside the viewBox limits (outside the area displayed).
Inkscape tends to produce a lot of crud that makes maintaining and changing a SVG outside the visual editor almost impossible. The following is the same image reduced to the bare essentials, including some changes:
I have removed the width/height values for the SVG. Giving dimensions in real-live values (here: mm) is not helpfull in most cases. and you said you wanted to produce bitmaps of variable size anyway. This amounts to overwriting these values, so you can leave them off in the source file.
The grafic elements have been moved inside the viewBox and all transformations resolved.
The grafics would not have filled the full viewBox width. I have widened them to a 100:10 ratio.
If you want to change the height/width ratio, you can set an attribute preserveAspectRatio="none" on the <svg> element and the set arbitrary output dimensions in the export program. The grafics will then scale non-uniformly and always fill the viewport.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 10">
<defs>
<linearGradient id="grad" gradientUnits="userSpaceOnUse" x1="50" y1="5" x2="50" y2="0">
<stop offset="0" stop-color="#ebecea" />
<stop offset="1" stop-color="#d6d7d5" />
</linearGradient>
</defs>
<path d="M 100,5 V 10 H 0 V 5 Z" fill="#d6d7d5" />
<path d="M 100,5 L 95,0 H 5 L 0,5 Z" fill="url(#grad)" />
</svg>

Related

How to externally control stroke of SVG pattern

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 192 96" height="480" fill="none" stroke="#000">
<defs>
<linearGradient id="gradInner" gradientUnits="userSpaceOnUse">
<stop stop-color="#070" offset="0"/>
<stop stop-color="#007" offset="1"/>
</linearGradient>
<g id="shape-s">
<path d="M48,4.5 H4.5 V43.5 H48"/>
<path d="M48,9 H24 A15,15 0 0,0 24,39 H48" stroke-width="2"/>
</g>
<pattern id="shape-m" width="48" height="48" patternUnits="userSpaceOnUse">
<path d="M0,4.5H48M0,43.5H48"/>
<path d="M0,9H48M0,39H48" stroke-width="2"/>
</pattern>
<g id="shape-e">
<path d="M 0,4.5 H43.5 V43.5 H0"/>
<path d="M 0,9 H24 A15,15 0 0,1 24,39 H0" stroke-width="2"/>
</g>
<g id="shape">
<rect fill="url(#shape-m)" stroke="none" x="48" width="48" height="48"/>
<use xlink:href="#shape-s"></use>
<use xlink:href="#shape-e" x="96"></use>
</g>
</defs>
<g stroke="url(#gradInner)">
<path d="M48,4.5 H4.5 V43.5 H48"/>
<path d="M48,4.5H96M48,43.5H96"/>
<path d="M96,4.5 h43.5 v39 H96"/>
<path d="M48,9 H24 A15,15 0 0,0 24,39 H48" stroke-width="2"/>
<path d="M48,9H96M48,39H96" stroke-width="2"/>
<path d="M96,9 h24 a15,15 0 0,1 0,30 H96" stroke-width="2"/>
</g>
<use xlink:href="#shape" y="48" stroke="url(#gradInner)"/>
</svg>
I am thinking that this is not possible, but I want to fish for a solution here before I throw in the towel. I am creating <use> elements with dynamic widths in JavaScript. I do it by grouping 3 elements: start/left, middle, end/right. The start element is always the same. The end element is positions by the x attribute of the <use>. The middle element is a <rect> filled with a <pattern> url.
The pattern was the only way I could see to be truly dynamic in width and support any kind of shape. But patterns also have serious limitations. The first problem is that the <rect> using the pattern must have no stroke of its own. The bigger problem is that I cannot control the stroke from the <use> element, I must set the stroke attribute on the <pattern> element itself. (of course the same limitations apply to fill as stroke)
Is there another solution for this? I want to be able to apply a gradient to the <use> element as a whole. A pattern does not allow for this. I can work around that, but it's clumsy and I'd rather not. Is there another solution for dynamic width that meets my needs?

How to have image inside svg background with radialGradient

I have svg element with some image inside it. I tried clipPath, but the results were not as expected
here's the code
<svg width="5396" height="829" enable-background="new" version="1.1" viewBox="0 0 1427.7 219.34" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="headera" cx="-334.2" cy="-79.465" r="713.85" gradientTransform="matrix(.35196 -.0011319 .0010719 .334 127.5 106)" gradientUnits="userSpaceOnUse">
<stop stop-color="#9d6173" offset="0"/>
<stop stop-color="#594b4f" offset="1"/>
</radialGradient>
<clipPath id="dodol">
<rect x="36.286" y="108.01" width="0" height="0" fill-opacity="0" stroke="#453030" stroke-linecap="round" stroke-linejoin="round" stroke-width=".052917"/>
<path d="m-535.38 77.813v6.0476c2.9078 113.15 92.911 174.65 152.71 167.82 169.93-23.912 248.91 44.042 387.75 45.474 56.339-1.17 204.04-22.034 204.04-22.034 78.053-5.4634 100.32 22.158 142.53 22.034 181.38-0.15553 205.7-119.12 449.25-127.14 104.33-1.7411 90.846-92.203 90.846-92.203z" fill="url(#headera)"/>
</clipPath>
</defs>
<g transform="matrix(1 0 0 .99999 535.38 -77.81)">
<rect x="36.286" y="108.01" width="0" height="0" fill-opacity="0" stroke="#453030" stroke-linecap="round" stroke-linejoin="round" stroke-width=".052917"/>
<path d="m-535.38 77.813v6.0476c2.9078 113.15 92.911 174.65 152.71 167.82 169.93-23.912 248.91 44.042 387.75 45.474 56.339-1.17 204.04-22.034 204.04-22.034 78.053-5.4634 100.32 22.158 142.53 22.034 181.38-0.15553 205.7-119.12 449.25-127.14 104.33-1.7411 90.846-92.203 90.846-92.203z" fill="url(#headera)"/>
</g>
<image clip-path="url(#dodol)" preserveAspectRatio="xMaxYMid meet" width="643px" height="50%" x="250" y="20" xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"/>
</svg>
the problem with the code is I can't resize the image as it should and some of the outgoing image that exceeds the svg element remains visible
what i want to achive is
the svg shape appears as the background for the image inside it
the image appereance clipped by svg shape
I can adjust the position and size of the image
thanks
I'm not very sure this is what you need. Please take a look.
The main idea is that you have to put the image inside the transformed group.
Also I've removed some useless elements (rects with width and height 0). Also instead of using the same path twice I'm reusing it with <use>
Yet another thing: I've changed the image size so that it keeps it's width/height ratio. It may not be what you want.
<svg viewBox="0 0 1427.7 219.34" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="headera" cx="-334.2" cy="-79.465" r="713.85" gradientTransform="matrix(.35196 -.0011319 .0010719 .334 127.5 106)" gradientUnits="userSpaceOnUse">
<stop stop-color="#9d6173" offset="0"/>
<stop stop-color="#594b4f" offset="1"/>
</radialGradient>
<clipPath id="dodol">
<path id="thePath" d="m-535.38 77.813v6.0476c2.9078 113.15 92.911 174.65 152.71 167.82 169.93-23.912 248.91 44.042 387.75 45.474 56.339-1.17 204.04-22.034 204.04-22.034 78.053-5.4634 100.32 22.158 142.53 22.034 181.38-0.15553 205.7-119.12 449.25-127.14 104.33-1.7411 90.846-92.203 90.846-92.203z" />
</clipPath>
</defs>
<g transform="matrix(1 0 0 .99999 535.38 -77.81)">
<use xlink:href="#thePath" fill="url(#headera)"/>
<image clip-path="url(#dodol)" width="600" height="529" x="250" y="20" xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"/>
</g>
</svg>

SVG — radial gradient with a smooth edged cutout

I'm trying to create a SVG background image like this (two colors, radial gradient, S-shape cutout with smooth edges):
It's quite easy to create a radial gradient (e.g. using this tool):
<!-- SVG syntax -->
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
<radialGradient id="g920" gradientUnits="userSpaceOnUse" cx="5.408560311284047%" cy="0%" r="93.04166277718278%">
<stop stop-color="#ed1c24" offset="0.1"/><stop stop-color="#003663" offset="1"/>
</radialGradient>
<rect x="-50" y="-50" width="101" height="101" fill="url(#g920)" />
</svg>
but is it possible to add the cutout too?
Lennis' answer was close. But you would get better results by combining the fill and the filter in one element, rather than try to use a blurry white shape to hide part of the gradient.
Note that the blur will affect any edge of the shape, including the top, left and right. So you need to make sure those edges are well away from (outside of) the edge of the SVG viewport.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
<defs>
<radialGradient id="g" gradientUnits="userSpaceOnUse" cx="5.4%" cy="0%" r="93%">
<stop stop-color="#ed1c24" offset="0.1"/>
<stop stop-color="#003663" offset="0.8"/>
</radialGradient>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation=".05" />
</filter>
</defs>
<path id="svg_1" d="M -0.5,-0.5
L 1.5,-0.5
L 1.5,0.5
L 1,0.5
C 1,0 0.6,0.1 0.5,0.25
C 0.4,0.4 0.1,0.4 0,0.25
L -0.5,0.25
Z"
fill="url(#g)" filter="url(#f1)"/>
</svg>
You could use a blur on a white element to make it look like a cutout.
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">
<defs>
<radialGradient id="g" gradientUnits="userSpaceOnUse" cx="5.4%" cy="0%" r="93%">
<stop stop-color="#ed1c24" offset="0.1"/>
<stop stop-color="#003663" offset="1"/>
</radialGradient>
<filter id="f1" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation=".05" />
</filter>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="url(#g)" />
<path id="svg_1" fill="white" d="m-0.1,0.5 l0,0.55l1.15,0l0,-0.53495c0,0 -0.1,-0.1 -0.5,0c-0.3,0.1 -0.5,0 -0.5,0l-0.1,0z" filter="url(#f1)"/>
</svg>
You could also try a meshgradient, it's in the svg 2.0 spec. At the moment no browser supports it that I know off.

How to make an SVG "line" with a border around it?

I have a little svg widget whose purpose is to display a list of angles (see image).
Right now, the angles are line elements, which only have a stroke and no fill. But now I'd like to have an "inside fill" color and a "stroke/border" around it. I'm guessing the line element can't handle this, so what should I use instead?
Notice that the line-endcap of the line's stroke is rounded. I'd like to maintain this effect in the solution.
<svg height="160" version="1.1" viewBox="-0.6 -0.6 1.2 1.2" width="160" xmlns="http://www.w3.org/2000/svg">
<g>
<g>
<circle class="sensorShape" cx="0" cy="0" fill="#FFF" r="0.4" stroke="black" stroke-width="0.015"/>
<line stroke="black" stroke-width="0.015" x1="0" x2="0" y1="-0.4" y2="0.4"/>
<line stroke="black" stroke-width="0.015" x1="-0.4" x2="0.4" y1="0" y2="0"/>
</g>
<g class="lsNorthAngleHandsContainer">
<line data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.04" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/>
<text font-size="0.08" transform="translate(-0.02316467632710395,-0.45125904029352226)">
348
</text>
</g>
</g>
</svg>
Add a second line, with same coordinates but thinner line width:
<g class="lsNorthAngleHandsContainer">
<line data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.04" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/>
<line data-angle="348" stroke="yellow" stroke-linecap="round" stroke-width="0.025" transform="rotate(348)" x1="0" x2="0" y1="0" y2="-0.4"/>
I found elegant solution inspired by illustration to W3C article about filling and stroking. Basically, you move path to definitions and use this definition to draw two elements:
<svg width="200" height="200" viewBox="0 0 100 100">
<defs>
<line id="line1" x1="25" x2="75" y1="25" y2="75"/>
</defs>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#line1" class="stroke"></use>
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#line1" class="line"></use>
</svg>
By using <defs> and <use> you can change only path element to update both lines. JSFiddle demo
It looks like your line is opaque, so you can just draw a thin line with the "inside" color on top of the thicker line with the "outside" color.
You could use a rect with rounded corners, but the math changes a bit:
<rect data-angle="348" stroke="red" stroke-linecap="round" stroke-width="0.02" fill="#FF0" transform="rotate(348, 0, 0)" x="-0.02" y="-0.4" width=".06" height=".4" rx=".03" ry=".03"/>
http://jsfiddle.net/RNAuP/
You can also do it with a path, even though it's tricky around the round bits:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!-- I often use entities to be able to change lot of numbers at once in static SVG, also kind of makes the paths more readable.
Obvisouly, if you're generating the path you can use the same variables in code to append to d -->
<!ENTITY handFill "0.01">
<!ENTITY handFill2 "0.02"><!-- Should be 2 * handFill to be centered -->
<!ENTITY handStroke "0.005"><!-- Should be less than handFill2 to not hide fill -->
]>
<svg height="160" version="1.1" viewBox="-0.6 -0.6 1.2 1.2" width="160" xmlns="http://www.w3.org/2000/svg">
<g>
<g>
<circle class="sensorShape" cx="0" cy="0" fill="#FFF" r="0.4" stroke="black" stroke-width="0.015"/>
<line stroke="black" stroke-width="0.015" x1="0" x2="0" y1="-0.4" y2="0.4"/>
<line stroke="black" stroke-width="0.015" x1="-0.4" x2="0.4" y1="0" y2="0"/>
</g>
<g class="lsNorthAngleHandsContainer">
<path d="
M -&handFill;,0 l0,-0.4
a &handFill;,&handFill; 0 0,1 &handFill2;,0
l 0,0.4
a &handFill;,&handFill; 0 0,1 -&handFill2;,0
" stroke="red" stroke-linecap="round" stroke-width="&handStroke;" fill="yellow" transform="rotate(348)" />
<text font-size="0.08" transform="translate(-0.02316467632710395,-0.45125904029352226)">
348
</text>
</g>
</g>
</svg>

how to repeat infinitely the whole svg

I mean after my SVG stops completing the animation I want the animation to start over again and end and then again start over and so on.
I tried:
<svg>
<animate repeatCount="indefinite"/>
</svg>
But it doesn't work.
See example animMotion01 in the w3 SVG spec for a fairly reduced example illustrating SVG animation (including use of repeatCount="indefinite"):
<svg width="5cm" height="3cm" viewBox="0 0 500 300"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<desc>Example animMotion01 - demonstrate motion animation computations</desc>
<rect x="1" y="1" width="498" height="298"
fill="none" stroke="blue" stroke-width="2" />
<!-- Draw the outline of the motion path in blue, along
with three small circles at the start, middle and end. -->
<path id="path1" d="M100,250 C 100,50 400,50 400,250"
fill="none" stroke="blue" stroke-width="7.06" />
<circle cx="100" cy="250" r="17.64" fill="blue" />
<circle cx="250" cy="100" r="17.64" fill="blue" />
<circle cx="400" cy="250" r="17.64" fill="blue" />
<!-- Here is a triangle which will be moved about the motion path.
It is defined with an upright orientation with the base of
the triangle centered horizontally just above the origin. -->
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z"
fill="yellow" stroke="red" stroke-width="7.06" >
<!-- Define the motion path animation -->
<animateMotion dur="6s" repeatCount="indefinite" rotate="auto" >
<mpath xlink:href="#path1"/>
</animateMotion>
</path>
</svg>

Resources