Tuesday, 12 May 2015

How To Work With SVG Patterns - Vanseo Design

How To Work With SVG Patterns - Vanseo Design


How To Work With SVG Patterns

Posted: 11 May 2015 05:30 AM PDT

Patterns are useful design elements. They can provide contrast, create a sense of depth, and add interest to a composition. SVG makes it easy to create and use patterns that are limited only by your imagination.

For the last few weeks, I've continued the series on SVG I started at the beginning of the year. I left off last week promising to talk about an element you can define and reuse and if you read the previous paragraph, you should be able to guess what that element is.

I want to talk about the <pattern> element and how you can work with patterns in SVG. I'll get through the basics of SVG patterns today and continue next week and show you how to build more complex patterns.

SVG Patterns

SVG patterns are used to fill or stroke SVG graphic objects. The graphic can either be an SVG or a bitmapped image and through the <pattern> element you tile the graphic at fixed x and y intervals to create a pattern from it.

You define a pattern inside a <pattern> element and you reference it through an id. If you read any of the last few posts in this series, referencing the pattern should be nothing new. Don't worry if it is new to you. The examples throughout this post should make it clear.

A Simple Pattern Example

Let's start with a simple example and build from there. Here I created a pattern from a repeating circle. Again, if you read any of the previous few posts in this series, most of this code should look familiar.

1  2  3  4  5  6  7  8  9  
<svg width="660" height="220">   <defs>     <pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">       <circle cx="10" cy="10" r="10" stroke="none" fill="#393" />     </pattern>   </defs>     <rect x="10" y="10" width="600" height="200" stroke="#630" stroke-width="5px" fill="url(#pattern)" />  </svg>

The pattern is defined inside <defs> tags. The <pattern> element doesn't display until referenced so you don't need the <defs>, but they are typically used. The <pattern> gets an id of pattern, which is referenced by the rectangle. The <rect> element uses the pattern as a fill and takes a solid color as a stroke.

Inside the <pattern> element is green circle with a radius of 10 (px). The cx and cy values (10px each) set the center of the first circle at the origin of the circle element, or its top left corner.

That might sound strange. How can a circle have a top left corner or any corner for that matter? Remember that you see SVG graphics through a rectangular viewport so the circle displays inside a rectangular region that does have a top left corner.

Before talking about the rest of the code let's see the resulting graphic. You can see it is a repeating pattern of green circles.

Now take a look at the attributes on the <pattern> element.

1  
<pattern id="pattern" x="0: y="0" width="20" height="20" patternUnits="userSpaceOnUse">

The x and y attributes define where the pattern starts. Here I set both to 0 so there's no offset before the pattern begins. Remember the circle is set so it's center is at the origin. Setting x and y to 0 aligns the center of the circle with the start of the pattern.

The width and height attributes define the width and height of the pattern to be repeated. Here I set both to be the same size as the diameter of the circle so when the pattern repeats it's one circle adjacent to the previous one.

Understanding the Attributes of the <pattern> Element

Let's change some of these value one at a time to see what effect each change has. Here's the resulting SVG when x and y are both changed to 10.

1  
<pattern id="pattern" x="10" y="10" width="20" height="20" patternUnits="userSpaceOnUse">

It might look the same at first glance, but focus your attention on the very first circle in the top left corner. Notice how it now starts at its edge instead of at it's center. In other words, changing the x or y values on the <pattern> element shifts the entire pattern by the amount x and y change.

Let's set x and y back to 0 and this time adjust the width and height of the pattern. Here's the result when both width and height are set to 25 instead of the 20 used in the original example.

1  
<pattern id="pattern" x="0" y="0" width="25" height="25" patternUnits="userSpaceOnUse">

The pattern starts in the same place as the original example, the center of the first circle. Notice that there is now some space in between circles. That's because the circle is 20px wide, but the pattern is now 25px in each direction, leaving 5px of empty space between circles.

In other words the width and height of the pattern determine where the next occurrence of the pattern is located and they allow you to include some additional whitespace in the pattern.

The final attribute I've included in the example is patternUnits, which defines the coordinate system for the pattern. It takes one of two possible values, userSpaceOnUse and objectBoundingBox.

  • userSpaceOnUse — x, y, width, and height represent values in the current user coordinate system. In other words the values don't scale.
  • objectBoundingBox (default) — x, y, width, and height represent values in the coordinate system of the bounding box (the element that gets the pattern). In other words the values do scale and a value of 1 on the pattern will be scaled to equal the width or height of the element that takes the pattern.

If the definitions are confusing, don't worry. Just remember that userSpaceOnUse doesn't scale the pattern and objectBoundingBox does.

With the reusable SVG elements we've talked about to this point in the series, I suggested you want the reusable element to scale most of the time. With patterns that's probably not as true and you'll likely use userSpaceOnUse more often than not. Of course, it depends on the specifics of your project.

In all the examples so far in this post, I've used userSpaceOnUse. Here's one with patternUnits is set to objectBoundingBox.

1  
<pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="objectBoundingBox">

What happened to the pattern? Because objectBoundingBox is the value of patternUnits, the values of 20 for width and height are scaled so they're equal to 600px (width) or 200px (height) depending on whether the direction is x or y. The next occurrence of the pattern starts just outside the rectangle.

When working with objectBoundingBox, the width and height need to be less than 1.0 for the pattern to display beyond it's first occurrence.

1  2  3  4  5  6  7  8  9  
<svg width="660" height="220">   <defs>     <pattern id="pattern" x="0" y="0" width="0.0333" height="0.1" patternUnits="objectBoundingBox">       <circle cx="10" cy="10" r="10" stroke="none" fill="#393" />     </pattern>   </defs>     <rect x="10" y="10" width="600" height="200" stroke="#630" stroke-width="5px" fill="url(#pattern)" />    </svg>

Here's the result.

You might be curious how I came up with the values of 0.0333 and 0.1 for x and y.

20 (circle height) ÷ 200 (rectangle height) = 0.1
20 (circle width) ÷ 600 (rectangle width) = 0.0333

I find userSpaceOnUse easier to work with and expect much of the time you'll want the pattern to remain the same size, but sometimes you might want the pattern to scale and you'll find objectBoundingBox useful.

Adding Patterns to Strokes

I mentioned you could add patterns to both fills and strokes, though I've only presented examples where a pattern is added as a fill. Let's try one as a stroke so you can see how it works.

1  2  3  4  5  6  7  8  9  
<svg width="660" height="220">   <defs>     <pattern id="pattern" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">       <circle cx="10" cy="10" r="10" stroke="none" fill="#393" />     </pattern>   </defs>     <rect x="10" y="10" width="600" height="200" stroke="url(#pattern)" stroke-width="20px" fill="#630" />  </svg>

The pattern is the same one we've seen throughout this post. It's a copy of the very first example I presented, with a couple of changes to the rectangle.

Earlier I referenced the pattern on the rectangle's fill. Here I added it to the stroke and used a solid color for the fill. I also bumped up the stroke-width to 20px so a single circle can fit inside its width.

Here's the result.

The pattern now fills the stroke instead of the background of the element. One thing to note is that shifting the pattern only shifts it within the border. It doesn't shift the entire border.

For example here's what the SVG looks like when I change both x and y on the pattern element to 10.

1  
<pattern id="pattern" x="10" y="10" width="20" height="20" patternUnits="userSpaceOnUse">

With a little trial and error you can come up with some interesting patterns.

Let's leave things here for today, though we're not yet finished talking about patterns. I'll pick things up again next week.

Closing Thoughts

Patterns can add a lot of interest to the elements in a composition and SVG makes them easy to create. You define patterns using simple shapes and lines and add them to SVG objects through the object's fill or stroke attributes.

Today I covered the very basics of patterns, but there's more. Next week I want to continue and talk about a few more attributes you can add to the <pattern> element. Then I'll show you how you can nest one pattern inside another to create even more complex patterns.

Download a free sample from my book Design Fundamentals.

The post How To Work With SVG Patterns appeared first on Vanseo Design.

This posting includes an audio/video/photo media file: Download Now