MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Шаблоны (Patterns)

Patterns, по моему мнению, одни из самых запутанных типов заполнения (fill types) в SVG. Несмотря на это ,они являются очень мощным инструментом, так что о них определенно стоит поговорить и понять хотя бы основные части. Как и градиенты, элементы <pattern> должны быть помещены в секцию <defs> в Вашем SVG-файле.

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="Gradient1">
      <stop offset="5%" stop-color="white"/>
      <stop offset="95%" stop-color="blue"/>
    </linearGradient>
    <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
      <stop offset="5%" stop-color="red"/>
      <stop offset="95%" stop-color="orange"/>
    </linearGradient>

    <pattern id="Pattern" x="0" y="0" width=".25" height=".25">
      <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
      <rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/>
      <circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
    </pattern>
  </defs>

  <rect fill="url(#Pattern)" stroke="black" width="200" height="200"/>
</svg>

ScreenshotLive sample

Внутри элемента <pattern> вы можете использовать любые другие основные фигуры, которые использовались ранее.  И каждая из них может быть стилизована, используя любые из возможных вариантов стилизаций, которые Вы изучали до этого, включая градиенты и прозрачность. Выше мы просто нарисовали два прямоугольника внутри нашего шаблона  (which overlap, and one of which is twice the size of the other and is used to fill in the entire pattern), и один круг.

Сбивающая с толку вещь - это определение единиц измерения и размера. В примере выше мы определили ширину и высоту соответствующими аттрибутами внутри паттерна, что бы указать как далеко паттерн будет "продолжаться", прежде чем начать повторяться. Также доступны x и y атрибуты для смещения стартовой точки этого прямоугольника в том месте где вы его отрисовываете. Причина по которой они тут использованы, описана ниже.

Как и с gradientUnits атрибутом, использованном ранее, у паттерна также есть атрибут patternUnits . Он определяет единицы измерения, которые принимают атрибуты. По дефолту используется значене "objectBoundingBox", (как и в предыдущем разделе). Так что значения от 0 до 1 будут масштабированы в зависимости от размеров объекта, к которому вы применяете паттерн. Поскольку в данном случае мы хотьм что бы шаблон повторялся 4 раза по горизонтали и вертикали, ширину и высоту мы установили в значение 0.25. Что означает 0.25 от размера целевого объекта

В отличие от градиентов, у паттернов есть 2ой атрибут - patternContentUnits, который описывает единицы измерения, используемые в базовых фигурах внутри элемента pattern. Дефолтное значение для этого атрибута -  userSpaceOnUse, противоположность атрибуту patternUnitsЭто означает что если Вы не укажете один или оба этих атрибута (patternContentUnits и/или patternUnits), фигуры, которые Вы будете рисовать внутри блока <pattern>, будут отрисованы в другой системе координат (отличной от той, которую использует паттерн). Это может немного запутывать, если Вы пишете код вручную.

To make this work in the above example, we had to consider the size of our box (200 pixels) and the fact that we wanted the pattern to repeat itself 4 times horizontally and vertically. That means that each pattern unit was a 50x50 square. The two rects and the circle inside the pattern were then sized to fit in a 50x50 box. Anything that we had drawn outside that box wouldn't have been shown. The pattern also had to be offset by 10 pixels so that it would start in the upper left corner of our box, so the x and y attributes of the pattern had to be adjusted to 10/200 = 0.05.

The caveat here is that if the object changes size, the pattern itself will scale to fit it, but the objects inside will not. So while we would still have 4 repeating units inside the pattern, the objects composing that pattern would remain the same size, and you end up with large areas of nothing in between them. By changing the patternContentUnits attribute, we can put all the elements into the same unit system:

 <pattern id="Pattern" width=".25" height=".25" patternContentUnits="objectBoundingBox">
   <rect x="0" y="0" width=".25" height=".25" fill="skyblue"/>
   <rect x="0" y="0" width=".125" height=".125" fill="url(#Gradient2)"/>
   <circle cx=".125" cy=".125" r=".1" fill="url(#Gradient1)" fill-opacity="0.5"/>
 </pattern>

Now, because the pattern content is in the same unit system as the pattern, we don't have to offset the box so that the pattern starts in the correct place, and if the object size was changed to a larger one, the pattern would automatically scale so that it had the same number of objects and repeats inside it. This contrasts with the "userSpaceOnUse" system, where if the object changes size the pattern would stay the same, and just repeat itself more times to fill the box.

As a slight aside, in Gecko circles seem to have trouble drawing if their radius is set to something less than 0.075 (even though they should be scaled up to have a much larger radius than that. This may be a bug in just the pattern element, or not a bug at all, I'm not sure). To work around that its probably best to avoid drawing in "objectBoundingBox" units unless you have to.

Neither of these uses is what one would normally think of when you think of a pattern. Patterns usually have a set size and repeat themselves independently of what an objects shape is. To create something like this, both the pattern and its contents must be drawn in the current userSpace, so that they don't change shape if the object does:

 <pattern id="Pattern" x="10" y="10" width="50" height="50" patternUnits="userSpaceOnUse">
   <rect x="0" y="0" width="50" height="50" fill="skyblue"/>
   <rect x="0" y="0" width="25" height="25" fill="url(#Gradient2)"/>
   <circle cx="25" cy="25" r="20" fill="url(#Gradient1)" fill-opacity="0.5"/>
 </pattern>

Of course, this means that the pattern won't scale if you change your object size later. All three of the above examples are shown below on a rectangle that has been slightly elongated to a height of 300px, but I should note its not an exhaustive picture, and there are other options available depending on your application.

Image:SVG_Pattern_Comparison_of_Units.png

Метки документа и участники

 Внесли вклад в эту страницу: valery-paschenkov
 Обновлялась последний раз: valery-paschenkov,