Reputation: 1374
I'm trying to discover the way to scale svg patterns so that the pattern is not cut by the bounds of the element using it. And yet so that pattern is beeing repeated to cover that element.
Let's say i have a 20px radius circle as a pattern. Applying it to 80px width element:
Now the element is beeing scaled to 90px, the pattern should stretch horizontally (no need to keep aspect ratio):
And at last, scale up above 90px adds another circle occurance (95px width in this example - aspect ratio is still ignored):
I can add some scripting to achieve that effect. But i'm curious about if i can get that behavior with pure SVG.
<svg style='display: block; height: 60px; width: 95px; '>
<defs>
<pattern patternUnits='userSpaceOnUse' viewBox='0 0 20 20' width='20' height='20' id='the_pattern'>
<circle cx='10' cy='10' r='10' stroke-width='0' fill='black'></circle>
</pattern>
</defs>
<rect x='0' y='0' width='80' height='20' fill='url(#the_pattern)'></rect>
<rect x='0' y='20' width='90' height='20' fill='url(#the_pattern)'></rect>
<rect x='0' y='40' width='95' height='20' fill='url(#the_pattern)'></rect>
</svg>
Upvotes: 1
Views: 563
Reputation: 101918
The answer is no. You cannot achieve that with pure SVG. Unless by "pure SVG" you include SVGs that have embedded Javascript (ie <script>
elements).
You could do it with CSS border-image
though.
https://developer.mozilla.org/en-US/docs/Web/CSS/border-image
Here's an example:
Ignore the fact that I've used a diamond image here. Just replace it with a circle version of the border image file. :)
.circle-border {
border-top: 30px solid;
border-image: url('https://interactive-examples.mdn.mozilla.net/media/examples/border-diamonds.png') 30 / 20px 0 0 0;
border-image-repeat: round;
}
div {
width: 80px;
height: 0px;
margin-bottom: 50px;
}
div:nth-child(2) {
width: 90px;
}
div:nth-child(3) {
width: 100px;
}
<div class="circle-border"></div>
<div class="circle-border"></div>
<div class="circle-border"></div>
Upvotes: 1
Reputation: 17248
Idea
You set the dimension of the container elements in 2 passes.
Pass 1:
Set the width of the container element to the value such that the desired number of pattern elements would just fit in horizontally. That would be 80 for the first two cases and 100 for the last.
Pass 2: Scale the container elements horizontally to the actual target widths ( 80, 90, 95 ).
In the code example below, the transform
attribute specifies the scaling. Note that the translate
verbs first shift the element position to the origin before scaling is applied and revert the translation thereafter (the verbs inside the `translate attribute are evaluated from right to left).
The x scaling factor is the quotient of target width and specified width, y just leaves the height as it is.
SVG Sample
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="8cm" height="4cm" viewBox="0 0 800 500" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="circlePattern" patternUnits="userSpaceOnUse"
x="0" y="0" width="20" height="20"
>
<circle cx="10" cy="10" r="10" fill="black" stroke="black" stroke-width="0"/>
</pattern>
</defs>
<!-- 1. base case 80 px width -->
<rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
x="100" y="200" width="80" height="20"
/>
<!-- 2. scale width to 90px -->
<rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
x="100" y="300" width="80" height="20"
transform="translate(100, 300) scale (1.125, 1.0) translate(-100, -300)"
/>
<!-- 3. scale width to 95px -->
<rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
x="100" y="400" width="100" height="20"
transform="translate(100, 400) scale (0.95, 1.0) translate(-100, -400)"
/>
</svg>
Inline Sample
The SVG parts pertaining to the question is the same as above.
.showcase {
/* background-image: url('#glyph');
background-size:100% 100%;*/
filter: url(#embedded);
}
.showcase:before {
display:block;
content:'';
color:transparent;
}
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="embedded" width="16cm" height="8cm" viewBox="0 0 800 500" version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<pattern id="circlePattern" patternUnits="userSpaceOnUse"
x="0" y="0" width="20" height="20"
>
<circle cx="10" cy="10" r="10" fill="black" stroke="black" stroke-width="0"/>
</pattern>
</defs>
<!-- 1. base case 80 px width -->
<rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
x="100" y="200" width="80" height="20"
/>
<!-- 2. scale width to 90px -->
<rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
x="100" y="300" width="80" height="20"
transform="translate(100, 300) scale (1.125, 1.0) translate(-100, -300)"
/>
<!-- 3. scale width to 95px -->
<rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
x="100" y="400" width="100" height="20"
transform="translate(100, 400) scale (0.95, 1.0) translate(-100, -400)"
/>
</svg>
<div id="showcase"/>
Upvotes: 0