英文:
Reset svg pattern origin point
问题
我正在尝试将一个三角形图案添加到SVG的rect
两端。其中rect
的宽度可以不同。问题是,根据rect
的起始和结束位置不同,图案可能会在三角形的中间开始。我需要它始终从起始位置开始。
我已经尝试设置patternUnits
,并调整了主SVG和图案的viewBox
,但没有成功。
此示例显示第2个和第3个条纹的图案对齐错误:
<svg width="346" height="100">
<defs>
<pattern x="0" y="0" id="zigZag" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="0" y="0" id="zagZig" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="12" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="30" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="51" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="49" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="101" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="121" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="119" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="201" width="2" height="100" fill="url(#zigZag)"></rect>
</svg>
这个示例显示将x位置更改为偶数可以正确对齐图案:
<svg width="346" height="100">
<defs>
<pattern x="0" y="0" id="zigZag" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="0" y="0" id="zagZig" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="12" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="30" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="50" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="48" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="100" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="120" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="118" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="200" width="2" height="100" fill="url(#zigZag)"></rect>
</svg>
如何在不更改由数据驱动的x位置的情况下获得这种对齐?
英文:
I'm trying to add a triangle pattern to each end of a svg rect
. Where the rect
can be varying widths. The problem is that depending on where the rect
starts and ends, the pattern can start in the middle of the triangle. I need it to always start at the beginning.
I've tried setting the patternUnits
, messing with the viewBox
for both the main svg and the pattern.
This example shows that the 2nd and 3rd stripe have wrongly aligned patterns
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<svg width="346" height="100">
<defs>
<pattern x="0" y="0" id="zigZag" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="0" y="0" id="zagZig" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="12" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="30" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="51" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="49" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="101" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="121" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="119" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="201" width="2" height="100" fill="url(#zigZag)"></rect>
</svg>
<!-- end snippet -->
This example shows that changing the the x position to an even number aligns the pattern correctly.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<svg width="346" height="100">
<defs>
<pattern x="0" y="0" id="zigZag" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="0" y="0" id="zagZig" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="12" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="30" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="50" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="48" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="100" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="120" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="118" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="200" width="2" height="100" fill="url(#zigZag)"></rect>
</svg>
<!-- end snippet -->
How can I get this alignment without having to changes the x position which is driven by data?
答案1
得分: 0
I don't think there is an easy way to make patterns work how you want here. Not automatically anyway.
One solution would be to create alternate versions of your patterns for the odd coordinate case. See zigZagOdd
and zagZigOdd
in the following example.
<svg width="100%" viewBox="0 0 346 100">
<defs>
<pattern x="0" y="0" id="zigZag" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="1" y="0" id="zigZagOdd" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="0" y="0" id="zagZig" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="1" y="0" id="zagZigOdd" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="12" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="30" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="51" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="49" width="2" height="100" fill="url(#zagZigOdd)"></rect>
<rect x="101" width="2" height="100" fill="url(#zigZagOdd)"></rect>
<rect x="121" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="119" width="2" height="100" fill="url(#zagZigOdd)"></rect>
<rect x="201" width="2" height="100" fill="url(#zigZagOdd)"></rect>
</svg>
However, if your goal was simply to reduce SVG file size and make it easy to apply your patterned fringes, then you could use a different method instead. I'd recommend the <use>
element.
<svg width="100%" viewBox="0 0 346 100">
<defs>
<pattern x="0" y="0" id="fringe" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<rect id="zigZag" width="2" height="100" fill="url(#fringe)"/>
<rect id="zagZig" width="2" height="100" fill="url(#fringe)" transform="scale(-1,1)"/>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<use x="14" xlink:href="#zagZig"/>
<use x="30" xlink:href="#zigZag"/>
<rect x="51" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<use x="51" xlink:href="#zagZig"/>
<use x="101" xlink:href="#zigZag"/>
<rect x="121" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<use x="121" xlink:href="#zagZig"/>
<use x="201" xlink:href="#zigZag"/>
</svg>
英文:
I don't think there is an easy way to make patterns work how you want here. Not automatically anyway.
One solution would be to create alternate versions of your patterns for the odd coordinate case. See zigZagOdd
and zagZigOdd
in the following example.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<svg width="100%" viewBox="0 0 346 100">
<defs>
<pattern x="0" y="0" id="zigZag" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="1" y="0" id="zigZagOdd" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="0" y="0" id="zagZig" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<pattern x="1" y="0" id="zagZigOdd" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse" patternTransform="rotate(180)">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="12" width="2" height="100" fill="url(#zagZig)"></rect>
<rect x="30" width="2" height="100" fill="url(#zigZag)"></rect>
<rect x="51" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="49" width="2" height="100" fill="url(#zagZigOdd)"></rect>
<rect x="101" width="2" height="100" fill="url(#zigZagOdd)"></rect>
<rect x="121" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<rect x="119" width="2" height="100" fill="url(#zagZigOdd)"></rect>
<rect x="201" width="2" height="100" fill="url(#zigZagOdd)"></rect>
</svg>
<!-- end snippet -->
However, if your goal was simply to reduce SVG file size and make it easy to apply your patterned fringes, then you could use a different method instead. I'd recommend the <use>
element.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
<svg width="100%" viewBox="0 0 346 100">
<defs>
<pattern x="0" y="0" id="fringe" width="2" height="6" viewBox="0 0 2 6" patternUnits="userSpaceOnUse">
<polygon points="0 0 2 3 0 6" style="fill: rgb(0, 0, 0);"></polygon>
</pattern>
<rect id="zigZag" width="2" height="100" fill="url(#fringe)"/>
<rect id="zagZig" width="2" height="100" fill="url(#fringe)" transform="scale(-1,1)"/>
</defs>
<rect width="346" height="100" rx="10" style="fill: rgba(255, 101, 35, 0.75);"></rect>
<rect x="14" width="16" height="100" style="fill: rgb(255, 101, 35);"></rect>
<use x="14" xlink:href="#zagZig"/>
<use x="30" xlink:href="#zigZag"/>
<rect x="51" width="50" height="100" style="fill: rgb(255, 101, 35);"></rect>
<use x="51" xlink:href="#zagZig"/>
<use x="101" xlink:href="#zigZag"/>
<rect x="121" width="80" height="100" style="fill: rgb(255, 101, 35);"></rect>
<use x="121" xlink:href="#zagZig"/>
<use x="201" xlink:href="#zigZag"/>
</svg>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论