Best practive to store SVG clipPaths globally - svg

I use the same clipPath in different inline SVG's what:
http://jsfiddle.net/meo/4nBnS/
<svg class="svg-graphic" width="0" height="0" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1">
<clipPath id="hex-mask">
<polygon points="270,0 0,160 0,485 270,645 560,485 560,160"></polygon>
</clipPath>
</svg>
<svg class="svg-graphic" width="180" height="200" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1">
<rect clip-path="url(#hex-mask)" x="0" y="0" width="100%" height="100%" fill="purple" />
</svg>
<svg class="svg-graphic" width="180" height="200" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" version="1.1">
<rect clip-path="url(#hex-mask)" x="0" y="0" width="100%" height="100%" fill="red" />
</svg>
Is it a good practice to do a 0x0px SVG element with all the paths i would like to use? Is there a better way to do this?

Typically you'd define the reusable components inside a <defs> element (in one of the <svg> elements on your page). It doesn't matter that much in which of the <svg> elements the <defs> is placed, but I'd recommend you to put it as the first child inside the first svg on the page (since the references can then be resolved directly on first use).

Related

how to use image as background in svg of guitar pick shape

I want fit image under guitar pick shaped svg element
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" version="1.1" baseProfile="full">
<defs>
<pattern id="img1" patternUnits="objectBoundingBox" x="0" y="0" width="1" height="1">
<image xlink:href="https://picsum.photos/100" width="100" height="100"/>
</pattern>
</defs>
<path d="M8022.333,4996.688a26.281,26.281,0,0,0-9.242-16.959,36.46,36.46,0,0,0-13.247-6.725c-7.448-2.2-15.127-2.789-24.92-2.885-2.04.143-6.126.319-10.184.74a54.277,54.277,0,0,0-15.884,3.963c-7.753,3.325-13.405,8.534-16.07,16.3a33.98,33.98,0,0,0-.728,18.988,81.581,81.581,0,0,0,8.237,20.654,122.339,122.339,0,0,0,22.1,29.732,38.463,38.463,0,0,0,9.7,7.155,10.077,10.077,0,0,0,9.76-.12,40.637,40.637,0,0,0,4.96-3.138,68.929,68.929,0,0,0,11.474-11.293,122.777,122.777,0,0,0,21.05-35.139C8021.942,5011.088,8023.451,5004.055,8022.333,4996.688Zm-69.877,13.931a4.186,4.186,0,0,0,.876,1.31,4.018,4.018,0,0,0,1.285.865,3.927,3.927,0,0,0,1.556.312,4.04,4.04,0,0,0,3.058-1.394l.3-.32,3.159,1.832-.416.508a7.635,7.635,0,0,1-6.1,3.056,7.428,7.428,0,0,1-2.956-.6,7.814,7.814,0,0,1-2.457-1.672,7.815,7.815,0,0,1,0-10.94,7.805,7.805,0,0,1,2.458-1.672,7.419,7.419,0,0,1,2.955-.6,7.637,7.637,0,0,1,6.1,3.055l.416.508-3.159,1.832-.3-.32a4.044,4.044,0,0,0-3.058-1.394,3.933,3.933,0,0,0-1.556.313,4.027,4.027,0,0,0-1.284.864,4.191,4.191,0,0,0-.877,1.31,4,4,0,0,0,0,3.15Zm24.893,6.026h-3.605v-9.312a2.55,2.55,0,0,0-.774-1.886,2.714,2.714,0,0,0-.836-.568,2.338,2.338,0,0,0-.955-.21,2.462,2.462,0,0,0-1.82.778,2.555,2.555,0,0,0-.773,1.886v9.312h-3.6V4996.51h3.6v5.195a4.915,4.915,0,0,1,2.594-.718,5.935,5.935,0,0,1,2.375.488,6.358,6.358,0,0,1,1.988,1.358l.007.007a6.529,6.529,0,0,1,1.319,2.042,6.42,6.42,0,0,1,.481,2.451Zm9.51-11.571a2.441,2.441,0,0,0-.989-.263,1.891,1.891,0,0,0-1.465.62,2.25,2.25,0,0,0-.645,1.588v9.625h-3.549v-9.625a5.937,5.937,0,0,1,3.22-5.313l.02-.01a5.592,5.592,0,0,1,2.42-.539,5.316,5.316,0,0,1,1.993.382,7.532,7.532,0,0,1,1.933,1.2l.615.506-3.288,1.951Zm18.373,11.571h-3.606v-1.42a7.281,7.281,0,0,1-1.337.875,6.158,6.158,0,0,1-2.817.688,7.68,7.68,0,0,1-3.026-.6,7.26,7.26,0,0,1-2.456-1.713,8.1,8.1,0,0,1-1.654-2.52,7.962,7.962,0,0,1,0-6.048,8.086,8.086,0,0,1,1.66-2.526,7.233,7.233,0,0,1,2.451-1.708,7.667,7.667,0,0,1,3.024-.6,6.521,6.521,0,0,1,2.926.657,6.42,6.42,0,0,1,1.228.792V4996.6h3.606Z" transform="translate(-7931.052 -4970.12)" fill="url(#img1)"/>
</svg>
</div>

how to do svg transform in percentage

I want to center the rect shape with something equivalent to
transform="translate(50% - 100,0)" for example:
<svg width="100%" height="100%" viewbox="0 0 100% 100%">
<g transform="translate(50% - 100,0)">
<rect width="200" height="100" fill="rgb(0,0,255)" />
</g>
</svg>
I can't find the right syntax.
You can use an inner <svg> element to do the percentage part via its x attribute then the rest with the <g> element as you already have.
I'm not sure what you intend with the viewBox but percentage values are not valid there. Looks like you just don't need that at all.
<svg width="100%" height="100%">
<svg x="50%" overflow="visible">
<g transform="translate(-100,0)">
<rect width="200" height="100" fill="rgb(0,0,255)" />
</g>
</svg>
</svg>

Use <use> within <clipPath> in <defs>

Can I use <use> to refer to a previously declared object inside a <clipPath> declaration?
So that it uses that element as definition for the clip path?
For example:
<defs>
<rect id="foo" width="20" height="20" />
<clipPath id="bar">
<use href="#foo" />
</clipPath>
</defs>
Yes, you can use the <use> command inside the clipPath declaration to refer to any external objects inside the svg file.
In the example below, clipPath cuts a 80 x 80px square from the image.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 300 300" style="border:1px solid red">
<defs>
<rect id="foo" width="80" height="80" />
<clipPath id="bar">
<use href="#foo" />
</clipPath>
</defs>
<image clip-path="url(#bar)" xlink:href="http://lorempixel.com/600/600/nature/1" x="20" y="20" height="100%" width="100%" />
</svg>
The red square shows the border of the entire canvas svg.

Edge not rendering SVG Symbol

I have two pairs of SVG patterns and symbols. The symbol holds and the SVG and the pattern shapes it. I use each pattern as a fill for a Circle.
This approach works fine in chrome but in edge only some svgs render in the circle. Below is an example, on chrome you should see both a shoe and a diamond. On Edge only the diamond renders even thou the approach is the same as the shoe.
CodePen Example
<svg width="660" height="600">
<defs>
<symbol xmlns="http://www.w3.org/2000/svg" id="symbol-shoe" viewBox="0 0 45 45">
</svg>
....SVG code
</svg>
<symbol xmlns="http://www.w3.org/2000/svg" id="symbol-diamond" viewBox="0 0 45 45">
<svg>
....SVG code
</svg>
</symbol>
<pattern id="pattern-diamond" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
<use xmlns="http://www.w3.org/2000/svg" x="6.59" y="6.59" width="31.819" height="31.819" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#symbol-diamond" />
<pattern id="pattern-shoe" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
<use xmlns="http://www.w3.org/2000/svg" x="6.59" y="6.59" width="31.819" height="31.819" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#symbol-shoe" />
</pattern>
</defs>
<circle fill="url(#pattern-shoe)" cx="150" cy="150" r="60" />
<circle fill="url(#pattern-diamond)" cx="150" cy="400" r="60" />

svg mask and bounding box

I need to apply mask to a different objects.
Mask should cover whole object (visible part of it). I put the mask inside one specific place, at the top of the page, changed maskContentUnits to objectBoundingBox, so it worked perfectly.
But then a problem appeared.
I made a fiddle to illustrate the problem: http://jsfiddle.net/8qdt7vjr/1/
<body>
<svg width="0" height="0">
<defs>
<mask id="mask1" maskContentUnits="objectBoundingBox">
<ellipse cx=".5" cy=".5" rx=".5" ry=".5" fill="white" />
</mask>
</defs>
</svg>
<svg class="svg" width="200" height="150" overflow="visible">
<rect x="-50" y="-50" width="350" height="250" fill="none" stroke="green" stroke-width="2" />
<svg id="zzz" x="0" y="0" width="100%" height="100%" overflow="visible" mask="url(#mask1)">
<rect x="-50" y="-50" width="350" height="250" fill="blue" fill-opacity=".3" />
</svg>
<rect width="100%" height="100%" fill="red" fill-opacity=".1" stroke="red" stroke-width="1" />
</svg>
</body>
In this fiddle i want to apply mask to svg element with id="zzz". But inside this element there is a rect element, that increases zzz's bounding box. In the fiddle it is rect, but in my project it is an image tag. zzz has overflow set to hidden (in the fiddle I changed it to visible, so it is easier to see the problem), so I have a specific portion of image visible inside zzz.
The real problem is that zzz's inner content increases zzz's bounding box.
In the fiddle I want ellipse mask to be inside red rectangle (visible zzz's area), but it is inside green rectangle (zzz's bounding box) instead.
So the main question is: is there any way to achieve this goal? Mask will be used by many elements with different sizes and content and I do not want to clone it.
Is there any way to do this without cloning mask inside each element?
Is there any way to reduce bounding box to visible area?
Is there any way to show a part of an image without expanding parent's bounding box?
Is there any other way to do this?
Is it something like this you try to achieve?
<body>
<svg width="0" height="0">
<defs>
<mask id="mask1" maskContentUnits="userSpaceOnUse">
<ellipse cx="100" cy="75" rx="100" ry="75" fill="white" />
</mask>
</defs>
</svg>
<svg class="svg" width="200" height="150" overflow="visible">
<rect x="-50" y="-50" width="350" height="250" fill="none" stroke="green" stroke-width="2" />
<svg id="zzz" x="0" y="0" width="100%" height="100%" overflow="visible" mask="url(#mask1)">
<rect x="-50" y="-50" width="350" height="250" fill="blue" fill-opacity=".3" />
</svg>
<rect width="100%" height="100%" fill="red" fill-opacity=".1" stroke="red" stroke-width="1" />
</svg>
</body>
Maybe using userSpaceOnUse instead of objectBoundingBox can help achieve what you want... In combination with nested svg elements you can define the userspace to use and with that the part the mask is applied to...

Resources