Is it possible to offset the pattern in an svg element by a certain amount?
The example below uses a pattern of circles that is embedded in a <g> element that has an x="70" offset. Unfortunately the offset only 'cuts' away a part of the element without moving the fill pattern.
html, body, svg {
margin: 0;
width: 100%;
height: 100%;
}
<svg class="gFlow" id="main" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern height="64" id="grid" patternunits="userSpaceOnUse" width="64">
<circle cx="32" cy="32" fill="orange" r="5"></circle>
</pattern>
</defs>
<rect fill="url(#grid)" height="100%" width="100%" x="70"></rect>
</svg>
Don't offset the rectangle, offset the pattern. You can specify the origin (offset) of a pattern using the x and y attributes. It doesn't matter if the offset is positive or negative, the pattern will still fill the element completely.
html, body, svg {
margin: 0;
width: 100%;
height: 100%;
}
svg {
border: solid 1px black;
}
<!-- Pattern with no offset -->
<svg class="gFlow" id="main" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern height="64" id="grid" patternUnits="userSpaceOnUse" width="64">
<circle cx="32" cy="32" fill="orange" r="5"></circle>
</pattern>
</defs>
<rect fill="url(#grid)" height="100%" width="100%"></rect>
</svg>
<!-- Pattern moved right by half the pattern width (32) -->
<svg class="gFlow" id="main" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern height="64" id="grid" patternUnits="userSpaceOnUse" width="64"
x="32" y="0">
<circle cx="32" cy="32" fill="orange" r="5"></circle>
</pattern>
</defs>
<rect fill="url(#grid)" height="100%" width="100%"></rect>
</svg>
Note: SVG attributes are technically case sensitive. That's changing, but you should use the correct case for backwards compatibility. patternunits should be patternUnits.
Related
This question already has answers here:
How to resize a svg
(2 answers)
Closed 17 hours ago.
I have the below SVG which I am using as a mask to overlay on an image, I am trying to make the circle responsive, so it shrinks on mobile devices but haven't had any luck using view box etc as it removes the mask, I am also trying to position the shadow to the bottom right of the circle, but again I am having trouble making it responsive.
Any help would be greatly appreciated.
svg {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2000 1000" preserveAspectRatio="xMidYMin slice">
<defs>
<mask id="mask" x="0" y="0">
<rect x="0" y="0" height="100%" width="100%" fill="#fff"/>
<circle cx="50%" cy="50%" r="250" />
</mask>
<pattern id="img" patternUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<image xlink:href="https://images.unsplash.com/photo-1507181179506-598491b53db4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=299b6fae13eb39086f5bb28029c61760&auto=format&fit=crop&w=1778&q=80" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
</pattern>
</defs>
<path id="Shadow" d="M462.231,0c19.593,38.355,29.045,88.448,36.926,138.3,9.125,75.59-104.323,237.333-194.755,250.24C246.323,389.921,51.569,371.964,0,313.148c46.559,91.147,141.283,153.59,250.655,153.59,155.395,0,281.365-125.97,281.365-281.365A280.22,280.22,0,0,0,462.231,0" opacity="0.2" />
<rect width="100%" height="100%" mask="url(#mask)" fill-opacity="1" fill="url(#img)" />
</svg>
Putting the path inside a g container allowed me to scale the shadow relative to the mask, hope this helps someone in the future.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" preserveAspectRatio="xMidYMid slice">
<defs>
<mask id="mask" x="0" y="0">
<rect x="0" y="0" height="100%" width="100%" fill="#fff"/>
<circle cx="50%" cy="50%" r="16.5%" />
</mask>
<pattern id="img" patternUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<image xlink:href="https://images.unsplash.com/photo-1507181179506-598491b53db4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=299b6fae13eb39086f5bb28029c61760&auto=format&fit=crop&w=1778&q=80" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
</pattern>
</defs>
<g>
<path id="Shadow" d="m 462.231 0 c 19.593 38.355 29.045 88.448 36.926 138.3 c 9.125 75.59 -104.323 237.333 -194.755 250.24 c -58.079 1.381 -252.833 -16.576 -304.402 -75.392 c 46.559 91.147 141.283 153.59 250.655 153.59 c 155.395 0 281.365 -125.97 281.365 -281.365 a 280.22 280.22 0 0 0 -69.789 -185.373" opacity="0.2" style="transform: scale(0.3) translate(579px, 650px);" />
<rect width="100%" height="100%" mask="url(#mask)" fill-opacity="1" fill="url(#img)" />
</g>
</svg>
I am having a problem with setting up shadow for a svg with mask applied to it. This is the code and jsfiddle: http://jsfiddle.net/3kxnmhfL/
.watch-video-svg {
width: 50px;
height: 50px;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" height="100%" width="100%" viewBox="0 0 100 100">
<defs>
<filter id="shadow">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<mask id="cut-off-bottom">
<circle cx="50%" cy="50%" r="50%" fill="white"/>
<polygon points="31,20, 31,77, 80,50" fill="black"/>
<!-- <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)" /> -->
</mask>
</defs>
<circle cx="50%" cy="50%" r="50%" fill="red" mask="url(#cut-off-bottom)" filter="url(#shadow)" />
</svg>
</div>
I'd like the shadow to appear only around svg circle and not containing div.
What could be the reason for shadow not showing up?
SVG filters have a "filter region". The filter region defines the area of pixels that the browser uses to store the result of the filters. The default filter region is the bounds of the element (that the filter is applied to) plus a margin around it to allow for filter elements that have results larger than the original element.
By default, that margin is 10% of the width and height, applied to all four sides. However in your case, a stdDeviation of "4" causes the blur to extend further than that 10% margin allowance. The result is a clipped blur, even though the viewBox has been enlarged enough to cater for the full blur.
To fix, this, you just need to bump up the filter region size. An allowance of 20% seems to work okay:
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
In addition, I've simplified the SVG by getting rid of the unnecessary mask. I also tweaked the viewBox to include the part of the blur that extends to the left.
.watch-video-svg {
width: 500px;
height: 500px;
background: linen;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="-5 0 120 120">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
</defs>
<circle cx="50" cy="50" r="50" fill="red" filter=url(#shadow) />
<polygon points="31,20, 31,77, 80,50" fill="white"/>
</svg>
</div>
You need to adjust your mask. Since your element is already a circle you don't need a circle in the mask, a rect to fill all the width/height is enough.
You need to also adjust the viewBox to leave some space for the shadow:
.watch-video-svg {
width: 50px;
height: 50px;
}
<div class="watch-video-svg">
<svg xmlns="http://www.w3.org/2000/svg" height="100%" width="100%" viewBox="0 0 120 120">
<defs>
<filter id="shadow">
<feDropShadow dx="4" dy="8" stdDeviation="4"/>
</filter>
<mask id="cut-off-bottom">
<rect x="0" y="0" width="100%" height="100%" fill="white"/>
<polygon points="31,20, 31,77, 80,50" fill="black"/>
</mask>
</defs>
<circle cx="50" cy="50" r="50" fill="red" mask="url(#cut-off-bottom)" filter=url(#shadow) />
</svg>
</div>
I have a SVG that needs to have a fixed height so its not super big when the width is 2000+ pixels (widescreens...)
The clipping mask should always be visible and the background image should be sliced and not be stretchend, i tried several things but nothing seems to work.
This is what i have now:
https://codepen.io/bucky208/pen/OEqbPp
div {
width: 100%;
}
<div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1381.5" preserveAspectRatio="none" style="display: block; position: absolute; width: 100%;height: 400px;">
<g id="clipgroup">
<defs>
<polygon id="mask" points="0,572.1 0,1381.3 1024,1040.5 1024,337.6 0,0"/>
</defs>
<clipPath id="mask_1_">
<use xlink:href="#mask" style="overflow:visible;"/>
</clipPath>
<g style="clip-path:url(#mask_1_);">
<image style="overflow:visible;" width="331" height="444" id="theimage" xlink:href="https://image.ibb.co/ipbNkJ/56_E0406_E5_C8_EF897.jpg" transform="matrix(3.1119 0 0 3.1111 -3.0528 -2.604167e-04)"></image>
</g>
</g>
</svg>
</div>
Do i need another wrapper around everything? How do i restore the image ratio?
Kind regards and a big thank you for everyone trying to help.
In order to get image fills to fill their container but preserve the original aspect ratio, a filter combined with objectBoundingBox sizing and preserveAspectRatio is your friend. The following code does what I think you want:
svg {
background: red;
}
#svgcont {
position: absolute;
width: 100%;
}
<div id="svgcont">
<svg x="0" y="0" width="100%" height="800px">
<defs>
<filter id="image-fill-nostretch" primitiveUnits="objectBoundingBox">
<feImage x="0" y="0" width="1" height="1" id="theimage" xlink:href="https://image.ibb.co/ipbNkJ/56_E0406_E5_C8_EF897.jpg" preserveAspectRatio="xMidYMid slice"/>
<feComposite operator="in" x1="SourceGraphic"/>
</filter>
<clipPath id="mask_1_" clipPathUnits="objectBoundingBox">
<polygon id="mask" points="0,0.5 0,1 1,0.75 1,0.25 0,0"/>
</clipPath>
</defs>
<g clip-path="url(#mask_1_)">
<rect width="100%"height="100%" x="0%" y="0%" filter="url(#image-fill-nostretch)"/>
</g>
</svg>
</div>
I try to draw a svg in my HTML Code to have a specific path/object with an background image.
The object should be a little bit responsive (using bootstrap), but filled with the image and the image should preseve its ratio.
<svg width="100%" height="370px" viewBox="0 0 1148.942 598.47" preserveAspectRatio="none" >
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="1153" height="680">
<image xlink:href="images/headerBackground.png" x="0" y="0" width="1153" height="680" />
</pattern>
</defs>
<path fill="url(#img1)" d="M1145.237,3.395H3.379v592c0,0,247.108-160.416,1141-99L1145.237,3.395z"/>
</svg>
You can see it here in the live demo:
https://liveweave.com/N5nib6
https://jsfiddle.net/zyyvd86g/
Maybe anybody can help? I hope the problem is clear enough.
You can use max-width:100% for the svg element and div element wrap on this svg.
You can get the responsive image
div {
width: 80%;
height: auto;
margin: 0 auto;
}
svg {
max-width: 100%;
height: auto;
}
<div>
<svg width="100%" height="370px" viewBox="0 0 1148.942 598.47" preserveAspectRatio="none" >
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="1153" height="680">
<image xlink:href="images/headerBackground.png" x="0" y="0" width="1153" height="680" />
</pattern>
</defs>
<path fill="url(#img1)" d="M1145.237,3.395H3.379v592c0,0,247.108-160.416,1141-99L1145.237,3.395z"/>
</svg>
</div>
IMO opinion, the simple solution to your problem is to use a different preserveAspectRatio on your SVG.
Using preserveAspectRatio="none" is going to stretch your SVG and cause problems.
I'm assuming you want to keep the shape of the "swoop" on the bottom of your path. Correct?
If that is the case, you might prefer to use
preserveAspectRatio="xMidYMax slice"
instead. This scales the SVG up to fill the full width of the SVG viewport, whilst keeping the aspect ratio the same, and keeping the bottom of the SVG viewBox on screen.
<svg width="100%" height="370px" viewBox="0 0 1148.942 598.47" preserveAspectRatio="xMidYMax slice">
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="1153" height="680">
<image xlink:href="http://lorempixel.com/1153/680/" x="0" y="0" width="1153" height="680" />
</pattern>
</defs>
<path fill="url(#img1)" d="M1145.237,3.395H3.379v592c0,0,247.108-160.416,1141-99L1145.237,3.395z"/>
</svg>
I have a svg-pattern applied to a polygon. It's working fine.
When I set another size on the svg-polygon, I don't want to scale the pattern.
I've tried all combinations I can think of with viewBox, patternUnits and patternContentUnits. The goal is to make the polygon work responsibly e.g. scale with it's parent element. Can anyone point me in the right direction?
<svg width="1000" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
<svg width="500" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
full example: https://codepen.io/anderssonola/pen/QqxKjJ
I solved temporarily by applying the pattern to a <rect>and then use css clip-pathto create the polygon and the pattern does not scale. I still would prefer to solve it with pure svg, since IE does not support the css clip-path.
.clip {
background: gray;
clip-path: polygon(0 0, 100% 0, 100% 30%, 0% 100%);
margin-bottom: 1em;
}
.clip.half {
width: 50%;
}
svg {
display: block;
height: 50px;
width: 100%
}
<div >
<svg>
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" >
<!-- pattern code -->
</svg>
</pattern>
<rect width="100%" height="50" fill="url(#pattern)" id="pattern-md"/>
</defs>
</svg>
</div>
<div class="clip">
<svg>
<use href="#pattern-md"/>
</svg>
</div>
<div class="clip half" >
<svg>
<use href="#pattern-md" />
</svg>
</div>
Working example: https://codepen.io/anderssonola/pen/oGyBMj/
You could always scale the pattern and size the polygon appropriately e.g.
<polygon transform="scale(2)" points="0,0 720,0 720,10 0,30" stroke="#bbb" fill="url(#pattern)" />