Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple fill pattern in svg : diagonal hatching

Tags:

svg

How would I fill an SVG shape, not with a single colour, an image or a gradient, but with a hatching pattern, diagonal if possible.

It's been 2 hours and I've found nothing (at least after 2005).

I figure a possible hack would be a hatched PNG that would serve as fill, but that is not ideal.

like image 551
Cystack Avatar asked Oct 25 '12 13:10

Cystack


9 Answers

I did not find anything for diagonal hatching on the internet either, so I'll share my solution here:

<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
  <path d="M-1,1 l2,-2
           M0,4 l4,-4
           M3,5 l2,-2" 
        style="stroke:black; stroke-width:1" />
</pattern>

(note the lower case "l" in the path expression)

The above creates a hatch with diagonal lines from the lower left to the upper right that are 4 pixels apart. Besides the diagonal line (M0,4 l4,-4) you also have to stroke the upper left and the lower right edges of the pattern area, since the line will otherwise be "constricted" due to clipping where it intersects the edges of the square.

Example of a pattern after applying the above steps, it shows how the pattern it titled to make the end product

To fill a rectangle with this pattern, do:

<rect x="0" y="0" width="100%" height="100%" fill="url(#diagonalHatch)"/>
like image 69
Ingo Kegel Avatar answered Oct 04 '22 09:10

Ingo Kegel


Use the patternTransform attribute to rotate a vertical (or horizontal) line segment. This method tiles seamlessly and uses the simplest possible path. The pattern width attribute controls how close parallel hatches are.

<pattern id="diagonalHatch" width="10" height="10" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse">
  <line x1="0" y1="0" x2="0" y2="10" style="stroke:black; stroke-width:1" />
</pattern>
like image 40
akarve Avatar answered Oct 04 '22 09:10

akarve


This code from http://bl.ocks.org/jfsiii/7772281 seems very clean and reusable:

svg {
  width: 500px;
  height: 500px;
}

rect.hbar {
  mask: url(#mask-stripe)
}

.thing-1 {
  fill: blue;
}


.thing-2 {
  fill: green;
}
    <!DOCTYPE html>
    <html>
      <head>
        <meta charset=utf-8 />
        <title>SVG colored patterns via mask</title>
      </head>
      <body>
        <svg>
          <defs>
            <pattern id="pattern-stripe" 
              width="4" height="4" 
              patternUnits="userSpaceOnUse"
              patternTransform="rotate(45)">
              <rect width="2" height="4" transform="translate(0,0)" fill="white"></rect>
            </pattern>
            <mask id="mask-stripe">
              <rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-stripe)" />
            </mask>      
          </defs>
    
          <!-- bar chart -->
          <rect class="hbar thing-2" x="0" y="0" width="50" height="100"></rect>
          <rect class="hbar thing-2" x="51" y="50" width="50" height="50"></rect>
          <rect class="hbar thing-2" x="102" y="25" width="50" height="75"></rect>
          
          <!-- horizontal bar chart -->
          <rect class="hbar thing-1" x="0" y="200" width="10" height="50"></rect>
          <rect class="hbar thing-1" x="0" y="251" width="123" height="50"></rect>
          <rect class="hbar thing-1" x="0" y="302" width="41" height="50"></rect>
          
        </svg>
      </body>
    </html>
like image 27
Nobu Avatar answered Oct 04 '22 09:10

Nobu


You may be able to create, what you want using a <pattern> tag.

As a starting point you might take this example of the respective MDN docu:

    <?xml version="1.0"?>
    <svg width="120" height="120" viewBox="0 0 120 120"
         xmlns="http://www.w3.org/2000/svg" version="1.1"
         xmlns:xlink="http://www.w3.org/1999/xlink">
     
        <defs>
            <pattern id="Triangle"
                     width="10" height="10"
                     patternUnits="userSpaceOnUse">
                <polygon points="5,0 10,10 0,10"/>
            </pattern>
        </defs>
     
        <circle cx="60" cy="60" r="50"
                fill="url(#Triangle)"/>
    </svg>
like image 40
Sirko Avatar answered Oct 04 '22 09:10

Sirko


One problem with drawing a diagonal line within a pattern is that when the pattern is tiled the lines won't always line up - especially at high zooms. (It depends on the SVG rendering engine you happen to be using). @Ingo's answer above attempts to resolve this by drawing in the triangles at the top-left and bottom-right corners - but again, using some rendering engines and high zooms, it doesn't always look best - and sometimes the line ends up looking a bit like a string of sausages.

Another approach is to draw a horizontal line in the pattern and rotate the pattern, e.g.

  <svg:svg viewBox="0 0 100 100" version="1.1"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<svg:defs>
  <svg:pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4" patternTransform="rotate(45 2 2)">
    <svg:path d="M -1,2 l 6,0" stroke="#000000" stroke-width="1"/>
  </svg:pattern>
</svg:defs>
<svg:rect x="0" y="0" height="100" width="100" fill="url(#diagonalHatch)"/>

like image 28
Marrow父 Avatar answered Oct 04 '22 09:10

Marrow父


These two resources are very helpful: https://bocoup.com/weblog/using-svg-patterns-as-fills https://github.com/iros/patternfills/blob/master/public/patterns.css

For example:

<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>
  <rect width='10' height='10' fill='red'/>
  <path d='M-1,1 l2,-2
           M0,10 l10,-10
           M9,11 l2,-2' stroke='orange' stroke-width='2'/>
</svg>
like image 33
jedierikb Avatar answered Oct 04 '22 09:10

jedierikb


This is a solution for diagonal lines using circle in pattern. You can change angle as per your requirements.

<svg width="500" height="500">
    <defs>
        <pattern id="transformedPattern"
            x="0" y="0" width="2" height="20"
            patternUnits="userSpaceOnUse"
            patternTransform="rotate(45)">

            <circle cx="1" cy="1" r="2" style="stroke: none; fill: #0000ff" />
        </pattern>
    </defs>

    <rect x="10" y="10" width="100" height="100"
        style="stroke: #000000; fill: url(#transformedPattern);" />
</svg>
like image 43
Muhammad Qasim Avatar answered Oct 04 '22 09:10

Muhammad Qasim


I tried with this sample. Hopefully, It can help you much.

<!DOCTYPE html>
<html>
  <head>
    <meta charset=utf-8 />
    <title>SVG colored patterns via mask</title>
  </head>
  <body>
    <svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <pattern id="stripes" viewBox="0,0,8,8" width="16" height="16" patternUnits="userSpaceOnUse">
          <polygon points="0,0 4,0 0,4" fill="yellow"></polygon>
          <polygon points="0,8 8,0 8,4 4,8" fill="yellow"></polygon>
          <polygon points="0,4 0,8 8,0 4,0" fill="green"></polygon>
          <polygon points="4,8 8,8 8,4" fill="green"></polygon>
        </pattern>
      </defs>
	  <rect fill="url(#stripes)" x="150" y="20" width="100" height="50" />
      <circle cx="50"  cy="50" r="50" fill="url(#stripes)"/>
    </svg>
  </body>
</html> 

Regards, Vu Phan

like image 22
Vu Phan Avatar answered Oct 04 '22 10:10

Vu Phan


SVG 2 has a hatch entity for specifically this purpose. From that page's example section:

<hatch hatchUnits="userSpaceOnUse" pitch="5" rotate="135">
  <hatchpath stroke="#a080ff" stroke-width="2"/>
</hatch>

This is a very easily configurable way to create hatches:

Illustration of hatch tag from the w3c

Furthermore the hatch path can also be customised:

<hatchpath stroke-width="1" d="C 0,4 8,6 8,10 8,14 0,16 0,20"/>
like image 22
bitmask Avatar answered Oct 04 '22 10:10

bitmask