重置 SVG 图案的起始点

huangapple go评论56阅读模式
英文:

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 -->

&lt;svg width=&quot;346&quot; height=&quot;100&quot;&gt;
&lt;defs&gt;
&lt;pattern x=&quot;0&quot; y=&quot;0&quot; id=&quot;zigZag&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;pattern x=&quot;0&quot; y=&quot;0&quot; id=&quot;zagZig&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot; patternTransform=&quot;rotate(180)&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;/defs&gt;
&lt;rect width=&quot;346&quot; height=&quot;100&quot; rx=&quot;10&quot; style=&quot;fill: rgba(255, 101, 35, 0.75);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;14&quot; width=&quot;16&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;12&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZig)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;30&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZag)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;51&quot; width=&quot;50&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;49&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZig)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;101&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZag)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;121&quot; width=&quot;80&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;119&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZig)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;201&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZag)&quot;&gt;&lt;/rect&gt;
&lt;/svg&gt;

<!-- 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 -->

    &lt;svg width=&quot;346&quot; height=&quot;100&quot;&gt;
&lt;defs&gt;
&lt;pattern x=&quot;0&quot; y=&quot;0&quot; id=&quot;zigZag&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;pattern x=&quot;0&quot; y=&quot;0&quot; id=&quot;zagZig&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot; patternTransform=&quot;rotate(180)&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;/defs&gt;
&lt;rect width=&quot;346&quot; height=&quot;100&quot; rx=&quot;10&quot; style=&quot;fill: rgba(255, 101, 35, 0.75);&quot;&gt;&lt;/rect&gt; 
&lt;rect x=&quot;14&quot; width=&quot;16&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;12&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZig)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;30&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZag)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;50&quot; width=&quot;50&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;48&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZig)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;100&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZag)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;120&quot; width=&quot;80&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;118&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZig)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;200&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZag)&quot;&gt;&lt;/rect&gt;
&lt;/svg&gt;

<!-- 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 -->

&lt;svg width=&quot;100%&quot; viewBox=&quot;0 0 346 100&quot;&gt;
&lt;defs&gt;
&lt;pattern x=&quot;0&quot; y=&quot;0&quot; id=&quot;zigZag&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;pattern x=&quot;1&quot; y=&quot;0&quot; id=&quot;zigZagOdd&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;pattern x=&quot;0&quot; y=&quot;0&quot; id=&quot;zagZig&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot; patternTransform=&quot;rotate(180)&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;pattern x=&quot;1&quot; y=&quot;0&quot; id=&quot;zagZigOdd&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot; patternTransform=&quot;rotate(180)&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;/defs&gt;
&lt;rect width=&quot;346&quot; height=&quot;100&quot; rx=&quot;10&quot; style=&quot;fill: rgba(255, 101, 35, 0.75);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;14&quot; width=&quot;16&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;12&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZig)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;30&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZag)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;51&quot; width=&quot;50&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;49&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZigOdd)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;101&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZagOdd)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;121&quot; width=&quot;80&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;119&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zagZigOdd)&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;201&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#zigZagOdd)&quot;&gt;&lt;/rect&gt;
&lt;/svg&gt;

<!-- 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 &lt;use&gt; element.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

&lt;svg width=&quot;100%&quot; viewBox=&quot;0 0 346 100&quot;&gt;
&lt;defs&gt;
&lt;pattern x=&quot;0&quot; y=&quot;0&quot; id=&quot;fringe&quot; width=&quot;2&quot; height=&quot;6&quot; viewBox=&quot;0 0 2 6&quot; patternUnits=&quot;userSpaceOnUse&quot;&gt;
&lt;polygon points=&quot;0 0 2 3 0 6&quot; style=&quot;fill: rgb(0, 0, 0);&quot;&gt;&lt;/polygon&gt;
&lt;/pattern&gt;
&lt;rect id=&quot;zigZag&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#fringe)&quot;/&gt;
&lt;rect id=&quot;zagZig&quot; width=&quot;2&quot; height=&quot;100&quot; fill=&quot;url(#fringe)&quot; transform=&quot;scale(-1,1)&quot;/&gt;
&lt;/defs&gt;
&lt;rect width=&quot;346&quot; height=&quot;100&quot; rx=&quot;10&quot; style=&quot;fill: rgba(255, 101, 35, 0.75);&quot;&gt;&lt;/rect&gt;
&lt;rect x=&quot;14&quot; width=&quot;16&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;use x=&quot;14&quot; xlink:href=&quot;#zagZig&quot;/&gt;
&lt;use x=&quot;30&quot; xlink:href=&quot;#zigZag&quot;/&gt;
&lt;rect x=&quot;51&quot; width=&quot;50&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;use x=&quot;51&quot; xlink:href=&quot;#zagZig&quot;/&gt;
&lt;use x=&quot;101&quot; xlink:href=&quot;#zigZag&quot;/&gt;
&lt;rect x=&quot;121&quot; width=&quot;80&quot; height=&quot;100&quot; style=&quot;fill: rgb(255, 101, 35);&quot;&gt;&lt;/rect&gt;
&lt;use x=&quot;121&quot; xlink:href=&quot;#zagZig&quot;/&gt;
&lt;use x=&quot;201&quot; xlink:href=&quot;#zigZag&quot;/&gt;
&lt;/svg&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2020年1月3日 14:05:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/59573900.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定