SVG 图案以图案不被切断的方式缩放
SVG patterns scaling the way pattern is not cut off
我正在尝试发现缩放 svg 图案的方法,以便图案不会被使用它的元素的边界切割。然而,这种模式正在重复以覆盖该元素。
假设我有一个 20px 半径的圆作为图案。
将它应用于 80px 宽度的元素:
现在元素被缩放到 90px,图案应该水平拉伸(不需要保持纵横比):
最后,放大到 90px 以上会添加另一个圆圈(本例中宽度为 95px - 宽高比仍然被忽略):
我可以添加一些脚本来实现这种效果。但我很好奇我是否可以使用纯 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>
想法
您分 2 次设置容器元素的尺寸。
第 1 轮:
将容器元素的宽度设置为使所需数量的图案元素刚好水平放置的值。前两个案例为 80,最后一个案例为 100。
第 2 关:
将容器元素水平缩放到实际目标宽度 ( 80, 90, 95 )。
在下面的代码示例中,transform
属性指定缩放比例。请注意,translate
动词在应用缩放之前首先将元素位置移动到原点,然后恢复翻译(`translate 属性中的动词从右到左计算)。
x缩放因子是目标宽度与指定宽度的商,y只保留高度。
SVG 样本
<?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>
内联示例
问题的SVG部分同上。
.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"/>
答案是否定的。您无法使用纯 SVG 实现这一点。除非 "pure SVG" 包含嵌入了 Javascript(即 <script>
元素)的 SVG。
不过你可以用 CSS border-image
来完成。
https://developer.mozilla.org/en-US/docs/Web/CSS/border-image
这是一个例子:
请忽略我在这里使用了钻石图片这一事实。只需将其替换为边框图像文件的圆形版本即可。 :)
.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>
我正在尝试发现缩放 svg 图案的方法,以便图案不会被使用它的元素的边界切割。然而,这种模式正在重复以覆盖该元素。
假设我有一个 20px 半径的圆作为图案。 将它应用于 80px 宽度的元素:
现在元素被缩放到 90px,图案应该水平拉伸(不需要保持纵横比):
最后,放大到 90px 以上会添加另一个圆圈(本例中宽度为 95px - 宽高比仍然被忽略):
我可以添加一些脚本来实现这种效果。但我很好奇我是否可以使用纯 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>
想法
您分 2 次设置容器元素的尺寸。
第 1 轮:
将容器元素的宽度设置为使所需数量的图案元素刚好水平放置的值。前两个案例为 80,最后一个案例为 100。
第 2 关: 将容器元素水平缩放到实际目标宽度 ( 80, 90, 95 )。
在下面的代码示例中,transform
属性指定缩放比例。请注意,translate
动词在应用缩放之前首先将元素位置移动到原点,然后恢复翻译(`translate 属性中的动词从右到左计算)。
x缩放因子是目标宽度与指定宽度的商,y只保留高度。
SVG 样本
<?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>
内联示例
问题的SVG部分同上。
.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"/>
答案是否定的。您无法使用纯 SVG 实现这一点。除非 "pure SVG" 包含嵌入了 Javascript(即 <script>
元素)的 SVG。
不过你可以用 CSS border-image
来完成。
https://developer.mozilla.org/en-US/docs/Web/CSS/border-image
这是一个例子:
请忽略我在这里使用了钻石图片这一事实。只需将其替换为边框图像文件的圆形版本即可。 :)
.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>