Home > Software design >  SVG using non-repetitive pattern as fill
SVG using non-repetitive pattern as fill

Time:12-06

I'm trying to use different SVG elements with a pattern as a fill, but the pattern doesn't get repeated for every element. I'm not sure if there's the possibility to repeat the pattern, but right now it looks as if there's a pattern and three circles create a mask over the pattern. What I want to achieve is the three circles clearly looking differently because each pattern resets for each circle and then it doesn't look 'cut out'.

I suppose a last-resort solution would be to create multiple patterns with different names for every element I use, then it'll work, but I'm hoping there's a less cumbersome way.

I tried:

  • Wrapping each element in a different SVG container
  • Appending ids to the elements and then in css target every id separately with the fill being the url

I made a codesandbox which shows my problem:

https://codesandbox.io/s/busy-ives-hv3rr?file=/index.html

CodePudding user response:

The solution @herrstrietzel posted is one way to go.

Another solution is to create variants of your original pattern, but with a different origin. You specify the origin using the x and y attributes.

<svg id="patternId" width="100%" height="100%">
        <defs>
          <pattern id="a" patternUnits="userSpaceOnUse" width="65" height="65" patternTransform="scale(2) rotate(0)">
            <rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)"/>
            <path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z"
                  stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)"/>
            <path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z"
                  stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)"/>
            <path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z"
                  stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)"/>
            <path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z"
                  stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)"/>
          </pattern>
          <pattern id="a2" href="#a" x="20" y="20"/>
          <pattern id="a3" href="#a" x="45" y="50"/>
        </defs>

        <svg height="200" width="200">
          <circle cx="50" cy="50" r="40" fill="url(#a)" />
        </svg>

        <svg height="200" width="200">
          <circle cx="100" cy="50" r="40" fill="url(#a2)" />
        </svg>

        <svg height="200" width="200">
          <circle cx="50" cy="100" r="40" fill="url(#a3)" />
        </svg>
      </svg>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Another alternative is to switch to objectBoundingBox units. So that the pattern is relative the the object it is applied to.

<svg id="patternId" width="100%" height="100%">
        <defs>
          <pattern id="a" patternUnits="objectBoundingBox" width="65" height="65">
            <g transform="scale(2)">
              <rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)"/>
              <path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z"
                    stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)"/>
              <path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z"
                    stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)"/>
              <path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z"
                    stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)"/>
              <path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z"
                    stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)"/>
            </g>
          </pattern>
          <pattern id="a2" href="#a" x="20" y="20"/>
          <pattern id="a3" href="#a" x="45" y="50"/>
        </defs>

        <svg height="200" width="200">
          <circle cx="50" cy="50" r="40" fill="url(#a)" />
        </svg>

        <svg height="200" width="200">
          <circle cx="100" cy="50" r="40" fill="url(#a)" />
        </svg>

        <svg height="200" width="200">
          <circle cx="50" cy="100" r="40" fill="url(#a)" />
        </svg>
      </svg>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

Applying transforms like transform="translate(50 50)" (instead of fixed x/y positioning would do the trick.

  <svg id="patternId" width="100%" height="100%">
    <defs>
      <pattern id="pattern-0" patternUnits="userSpaceOnUse" width="65" height="65" patternTransform="scale(2) rotate(0)" >
        <g id="patternInner">
          <rect x="0" y="0" width="100%" height="100%" fill="hsla(0,0%,100%,1)" />
          <path d="M.5.5v12h12V.5H.5zm13 13v12h12v-12h-12zm-13 13v12h12v-12H.5zm26 13v12h12v-12h-12zm13 13v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(258.5,59.4%,59.4%,1)" />
          <path d="M26.5.5v12h12V.5h-12zm0 13v12h12v-12h-12zm13 13v12h12v-12h-12zm-39 13v12h12v-12H.5zm0 13v12h12v-12H.5z" stroke-width="1" stroke="none" fill="hsla(339.6,82.2%,51.6%,1)" />
          <path d="M13.5.5v12h12V.5h-12zm39 13v12h12v-12h-12zm-39 13v12h12v-12h-12zm39 0v12h12v-12h-12zm-26 26v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(198.7,97.6%,48.4%,1)" />
          <path d="M52.5.5v12h12V.5h-12zm-13 13v12h12v-12h-12zm0 26v12h12v-12h-12zm13 0v12h12v-12h-12zm-39 13v12h12v-12h-12z" stroke-width="1" stroke="none" fill="hsla(33, 90%, 65%, 1)" />
        </g>
      </pattern>
      <pattern id="pattern-1" href="#pattern-0" x="80" y="80" patternTransform="scale(2) rotate(45)" />
    </defs>
    <circle cx="50" cy="50" r="40" fill="url(#pattern-0)" />
    <circle cx="50" cy="50" r="50" fill="url(#pattern-0)" transform="translate(50 33)"  />
    <circle cx="50" cy="50" r="50" fill="url(#pattern-1)" transform="translate(50 33)"  />
    <rect x="0" y="0" width="50" height="50" stroke="#fff" stroke-width="1" transform="translate(10 60)" fill="url(#pattern-0)" />
  </svg>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Worth noting: duplicating patterns for slightly modified usage is pretty straight forward, since the <pattern> element supports referencing/reusing previously defined patterns via href attribute (similar to <use>):

  <pattern id="pattern-1" href="#pattern-0" x="80" y="80" patternTransform="scale(2) rotate(45)" />

Would result in a rotated pattern sharing all properties of the initially defined pattern.

  •  Tags:  
  • svg
  • Related