动态调整单个形状的大小而不缩放整个 SVG
Resizing single shapes dynamically without scaling the whole SVG
我有一个 SVG 箭头,我想根据包装的宽度改变它的长度 DIV(例如)。
我之前的所有尝试都导致了这种行为(缩放整个 SVG):
而不是这个,我想实现这个行为:
是否可以通过简单地向代码添加百分比值来改变 SVG 内部的单个形状?如果没有,我该如何执行?
SVG 代码:
<svg width="35px" viewBox="0 0 35 985" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
通过使用符号,您可以制作所需的形状并将它们包含在其中。然后要延长中间部分,只需制作一条新路径并使线条更长。使用 transform
属性
可以将它们放置在您喜欢的任何位置
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="base">
<g xmlns="http://www.w3.org/2000/svg">
<path fill="#5FDBC6" d="M0,0 L0,20 L4,20 L4,0z"></path>
</g>
</symbol>
<symbol id="triangle" >
<g>
<path fill="#5FDBC6" d="M0,0 L15,10 L0,20z"></path>
</g>
</symbol>
<path stroke-width="4" stroke="#5FDBC6" d="M0,10 L100,10"></path>
<g class="first" transform="translate(0,00)">
<use xlink:href="#base" />
</g>
<g class="first" transform="translate(90,00)">
<use xlink:href="#triangle" />
</g>
<path stroke-width="4" stroke="#5FDBC6" d="M0,50 L200,50"></path>
<g class="first" transform="translate(0,40)">
<use xlink:href="#base" />
</g>
<g class="first" transform="translate(200,40)">
<use xlink:href="#triangle" />
</g>
</svg>
** 已编辑 **
此行为是由您在 <svg>
上的 viewBox
属性引起的。默认情况下会保留 SVG 的纵横比。您希望在 #Triangle
和 #Rectangle-3
上有此行为,但在 #Rectangle-2
上不会(您希望 height
增加,但 width
保持不变)。
我想你会想要添加 preserveAspectRatio=none
到你的 <svg>
内联 CSS 然后做一些调整(因为这会弄乱你的 #Triangle
和 #Rectangle-3
- 或者,您可以尝试将 #triangle-2
的 height
更改为与包装器 div 相同的高度(在我的 JS fiddle我是这样做的,将 #Triangle-2
s 的高度设置为 25vh。玩 window 的高度 - #Rectangle-2
的高度拉长但不改变宽度,虽然我还没有让你的 #Rectangle-3
动态地粘在 #Rectangle-2
的底部(#Rectangle-3
粘在 window 的底部):https://jsfiddle.net/KyleVassella/dnagft6q/6/
我想你会知道如何解决这个问题,但无论哪种方式,我都会继续努力,与此同时你可以在这里阅读,那里有更多关于这个主题的信息:
How can I make an svg scale with its parent container?
作为一般规则,无法创建部分无法缩放的可缩放 SVG。如果一个 SVG 有一个 viewBox,并且你缩放它,那么所有的内容都会缩放。无法将某些内容标记为不受缩放影响。
最接近的是将缩放限制在 X 轴上。但是箭头仍然会伸展。
<svg width="35px" height="150px" viewBox="0 0 35 985" preserveAspectRatio="none">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
<svg width="35px" height="300px" viewBox="0 0 35 985" preserveAspectRatio="none">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
如果你想要一个通用的解决方案,那么你必须监视调整大小事件并动态更新 SVG。
有限的偷偷摸摸的聪明解决方案...
综上所述,有一种巧妙的技术可以在有限的情况下发挥作用。限制是:
- SVG 仅在一个方向上拉伸。
- "non-scaling" 部分位于拉伸的任一端或两端
- 端部是实心的,没有任何孔。
- 您可以接受 SVG 的背景是纯色而不是透明的。
这是使用此技术实现的形状演示。如果您水平调整 window 的大小,您会看到它适当地伸展。:
<svg width="100%" height="35px">
<svg viewBox="0 0 1 1" preserveAspectRatio="none">
<rect x="0" y="0" width="1" height="1" fill="white"/>
<rect x="0" y="0.4" width="1" height="0.2" fill="#5FDBC6"/>
</svg>
<svg viewBox="0 0 0.2 1" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="0.2" height="1" fill="#5FDBC6"/>
</svg>
<svg viewBox="0 0 0.8 1" preserveAspectRatio="xMaxYMid">
<rect x="0" y="0" width="0.8" height="1" fill="white"/>
<polygon points="0,0 0.8,0.5 0,1" fill="#5FDBC6"/>
</svg>
</svg>
对于这个特定的用例,我想我会采用 CSS 方法,如果您不能使用伪元素,它可能会(取决于您的标记)添加一个 html 元素,但它不需要 JS 或手动输入 stroke-width 或 transform 元素的值。
这是使用段落标记制作此箭头的方法:
p {
position: relative;
max-width: 300px;
border-bottom: 4px solid #5FDBC6;
padding-bottom:6px;
}
p:nth-child(2) {max-width: 400px;}
p:nth-child(3) {max-width: 200px;}
p::before, p::after{
content:'';
position:absolute;
bottom:-8px;
}
p::before {
height: 12px;
left:0;
border-left: 4px solid #5FDBC6;
}
p::after{
right:-4px;
border-style:solid;
border-width:6px 0 6px 8px;
border-color:transparent transparent transparent #5FDBC6;
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. a dapibus, tincidunt velit eget, rutrum urna.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in purus risus. Ut id est suscipit, tincidunt sem a, fermentum magna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut rutrum ac ligula</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in purus risus. Ut id est suscipit, tincidunt sem a, fermentum magna.</p>
是的,您可以在 svg 中使用百分比。
基本形状非常简单。你可以把你的主要矩形写成
<rect x="0" y="5" width="100%" height="10"/>
你的第二个 rect 更简单,因为它一直位于 0,0
<rect x="0" y="0" width="10" height="20"/>
但是箭头在路径和多边形中存在问题,您不能使用百分比。要解决此问题,有一个两步解决方案。
先把路径放在符号元素中:
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
现在您可以像放置矩形一样放置此符号...简单...
<use xlink:href="#arrow" x="100%" y="0" width="20" height="20"/>
但现在您的箭头开始 100% 并且完全在您的视口之外。你可以在你的 svg 上设置 overflow: visible 并完成它,但这不是我们想要的......我们希望箭头在 100% 处结束。但这也很简单,我们知道箭头是 20px 宽。所以只需将 use 翻译回 20px:
<use xlink:href="#arrow" x="100%" y="0" width="20" height="20" transform="translate(-20 0)"/>
使用这种方法,您可以根据百分比将任何形状放置在任何位置...
为了扭曲它,你的完整 svg 现在看起来像这样:
<svg id="svg" height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
这里是使用 3 种不同宽度的 svg 的片段:
svg:nth-of-type(1) {
width: 100px
}
svg:nth-of-type(2) {
width: 200px
}
svg:nth-of-type(3) {
width: 300px
}
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
<br/>
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
<br/>
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
我有一个 SVG 箭头,我想根据包装的宽度改变它的长度 DIV(例如)。
我之前的所有尝试都导致了这种行为(缩放整个 SVG):
而不是这个,我想实现这个行为:
是否可以通过简单地向代码添加百分比值来改变 SVG 内部的单个形状?如果没有,我该如何执行?
SVG 代码:
<svg width="35px" viewBox="0 0 35 985" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
通过使用符号,您可以制作所需的形状并将它们包含在其中。然后要延长中间部分,只需制作一条新路径并使线条更长。使用 transform
属性
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="base">
<g xmlns="http://www.w3.org/2000/svg">
<path fill="#5FDBC6" d="M0,0 L0,20 L4,20 L4,0z"></path>
</g>
</symbol>
<symbol id="triangle" >
<g>
<path fill="#5FDBC6" d="M0,0 L15,10 L0,20z"></path>
</g>
</symbol>
<path stroke-width="4" stroke="#5FDBC6" d="M0,10 L100,10"></path>
<g class="first" transform="translate(0,00)">
<use xlink:href="#base" />
</g>
<g class="first" transform="translate(90,00)">
<use xlink:href="#triangle" />
</g>
<path stroke-width="4" stroke="#5FDBC6" d="M0,50 L200,50"></path>
<g class="first" transform="translate(0,40)">
<use xlink:href="#base" />
</g>
<g class="first" transform="translate(200,40)">
<use xlink:href="#triangle" />
</g>
</svg>
** 已编辑 **
此行为是由您在 <svg>
上的 viewBox
属性引起的。默认情况下会保留 SVG 的纵横比。您希望在 #Triangle
和 #Rectangle-3
上有此行为,但在 #Rectangle-2
上不会(您希望 height
增加,但 width
保持不变)。
我想你会想要添加 preserveAspectRatio=none
到你的 <svg>
内联 CSS 然后做一些调整(因为这会弄乱你的 #Triangle
和 #Rectangle-3
- 或者,您可以尝试将 #triangle-2
的 height
更改为与包装器 div 相同的高度(在我的 JS fiddle我是这样做的,将 #Triangle-2
s 的高度设置为 25vh。玩 window 的高度 - #Rectangle-2
的高度拉长但不改变宽度,虽然我还没有让你的 #Rectangle-3
动态地粘在 #Rectangle-2
的底部(#Rectangle-3
粘在 window 的底部):https://jsfiddle.net/KyleVassella/dnagft6q/6/
我想你会知道如何解决这个问题,但无论哪种方式,我都会继续努力,与此同时你可以在这里阅读,那里有更多关于这个主题的信息:
How can I make an svg scale with its parent container?
作为一般规则,无法创建部分无法缩放的可缩放 SVG。如果一个 SVG 有一个 viewBox,并且你缩放它,那么所有的内容都会缩放。无法将某些内容标记为不受缩放影响。
最接近的是将缩放限制在 X 轴上。但是箭头仍然会伸展。
<svg width="35px" height="150px" viewBox="0 0 35 985" preserveAspectRatio="none">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
<svg width="35px" height="300px" viewBox="0 0 35 985" preserveAspectRatio="none">
<g id="Group" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(0.000000, 0.000000)">
<rect id="Rectangle-2" fill="#5FDCC7" x="12" y="19.7987928" width="11" height="100%"></rect>
<polygon id="Triangle" fill="#5FDBC6" points="17.5 0 35 20.7887324 0 20.7887324"></polygon>
<rect id="Rectangle-3" fill="#5FDBC6" x="0" y="973.110664" width="35" height="11"></rect>
</g>
</svg>
如果你想要一个通用的解决方案,那么你必须监视调整大小事件并动态更新 SVG。
有限的偷偷摸摸的聪明解决方案...
综上所述,有一种巧妙的技术可以在有限的情况下发挥作用。限制是:
- SVG 仅在一个方向上拉伸。
- "non-scaling" 部分位于拉伸的任一端或两端
- 端部是实心的,没有任何孔。
- 您可以接受 SVG 的背景是纯色而不是透明的。
这是使用此技术实现的形状演示。如果您水平调整 window 的大小,您会看到它适当地伸展。:
<svg width="100%" height="35px">
<svg viewBox="0 0 1 1" preserveAspectRatio="none">
<rect x="0" y="0" width="1" height="1" fill="white"/>
<rect x="0" y="0.4" width="1" height="0.2" fill="#5FDBC6"/>
</svg>
<svg viewBox="0 0 0.2 1" preserveAspectRatio="xMinYMid">
<rect x="0" y="0" width="0.2" height="1" fill="#5FDBC6"/>
</svg>
<svg viewBox="0 0 0.8 1" preserveAspectRatio="xMaxYMid">
<rect x="0" y="0" width="0.8" height="1" fill="white"/>
<polygon points="0,0 0.8,0.5 0,1" fill="#5FDBC6"/>
</svg>
</svg>
对于这个特定的用例,我想我会采用 CSS 方法,如果您不能使用伪元素,它可能会(取决于您的标记)添加一个 html 元素,但它不需要 JS 或手动输入 stroke-width 或 transform 元素的值。
这是使用段落标记制作此箭头的方法:
p {
position: relative;
max-width: 300px;
border-bottom: 4px solid #5FDBC6;
padding-bottom:6px;
}
p:nth-child(2) {max-width: 400px;}
p:nth-child(3) {max-width: 200px;}
p::before, p::after{
content:'';
position:absolute;
bottom:-8px;
}
p::before {
height: 12px;
left:0;
border-left: 4px solid #5FDBC6;
}
p::after{
right:-4px;
border-style:solid;
border-width:6px 0 6px 8px;
border-color:transparent transparent transparent #5FDBC6;
}
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. a dapibus, tincidunt velit eget, rutrum urna.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in purus risus. Ut id est suscipit, tincidunt sem a, fermentum magna. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Ut rutrum ac ligula</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras in purus risus. Ut id est suscipit, tincidunt sem a, fermentum magna.</p>
是的,您可以在 svg 中使用百分比。
基本形状非常简单。你可以把你的主要矩形写成
<rect x="0" y="5" width="100%" height="10"/>
你的第二个 rect 更简单,因为它一直位于 0,0
<rect x="0" y="0" width="10" height="20"/>
但是箭头在路径和多边形中存在问题,您不能使用百分比。要解决此问题,有一个两步解决方案。
先把路径放在符号元素中:
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
现在您可以像放置矩形一样放置此符号...简单...
<use xlink:href="#arrow" x="100%" y="0" width="20" height="20"/>
但现在您的箭头开始 100% 并且完全在您的视口之外。你可以在你的 svg 上设置 overflow: visible 并完成它,但这不是我们想要的......我们希望箭头在 100% 处结束。但这也很简单,我们知道箭头是 20px 宽。所以只需将 use 翻译回 20px:
<use xlink:href="#arrow" x="100%" y="0" width="20" height="20" transform="translate(-20 0)"/>
使用这种方法,您可以根据百分比将任何形状放置在任何位置...
为了扭曲它,你的完整 svg 现在看起来像这样:
<svg id="svg" height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
这里是使用 3 种不同宽度的 svg 的片段:
svg:nth-of-type(1) {
width: 100px
}
svg:nth-of-type(2) {
width: 200px
}
svg:nth-of-type(3) {
width: 300px
}
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
<br/>
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>
<br/>
<svg height="20px" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="arrow" viewBox="0 0 20 20" width="20" height="20">
<path d="M0,0L20 10L0 20z" />
</symbol>
<g id="Group" fill="#5FDCC7">
<rect x="0" y="5" width="100%" height="10" transform="translate(-20 0)" />
<rect x="0" y="0" width="10" height="20" />
<use xlink:href="#arrow" width="20" height="20" x="100%" y="0" transform="translate(-20 0)" />
</g>
</svg>