SVG паттерны масштабируют так, чтобы паттерн не обрезался - PullRequest
0 голосов
/ 13 апреля 2020

Я пытаюсь найти способ масштабирования SVG-шаблонов, чтобы шаблон не обрезался границами элемента, использующего его. И все же, так что рисунок повторяется, чтобы покрыть этот элемент.

Допустим, у меня есть круг с радиусом 20 пикселей в качестве шаблона. Применяя его к элементу шириной 80px:

80px width element

Теперь элемент масштабируется до 90px, рисунок должен растягиваться горизонтально (не нужно сохранять соотношение сторон) :

90px width element

И, наконец, увеличение выше 90px добавляет еще одну окружность (ширина 95px в этом примере - соотношение сторон по-прежнему игнорируется):

95px width element

Я могу добавить некоторые сценарии для достижения этого эффекта. Но мне любопытно, смогу ли я получить такое поведение с чистым SVG.

<svg style='display: block; height: 60px; width: 95px; '>
    <defs>
        <pattern patternUnits='userSpaceOnUse' viewBox='0 0 20 20' width='20'  height='20' id='the_pattern'>
            <circle cx='10' cy='10' r='10' stroke-width='0' fill='black'></circle>
        </pattern>
    </defs>

    <rect x='0' y='0' width='80' height='20' fill='url(#the_pattern)'></rect>
    <rect x='0' y='20' width='90' height='20' fill='url(#the_pattern)'></rect>
    <rect x='0' y='40' width='95' height='20' fill='url(#the_pattern)'></rect>

</svg>

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Ответ - нет. Вы не можете достичь этого с чистым SVG. Если только «чистый SVG» не включает SVG со встроенными Javascript (ie <script> элементами).

Вы можете сделать это с помощью CSS border-image.

https://developer.mozilla.org/en-US/docs/Web/CSS/border-image

Вот пример:

Не обращайте внимания на тот факт, что я использовал алмазное изображение здесь. Просто замените его круговой версией файла изображения границы. :)

.circle-border {
  border-top: 30px solid;
  border-image: url('https://interactive-examples.mdn.mozilla.net/media/examples/border-diamonds.png') 30 / 20px 0 0 0;
  border-image-repeat: round;
}

div {
  width: 80px;
  height: 0px;
  margin-bottom: 50px;
}

div:nth-child(2) {
  width: 90px;
}

div:nth-child(3) {
  width: 100px;
}
<div class="circle-border"></div>
<div class="circle-border"></div>
<div class="circle-border"></div>
0 голосов
/ 13 апреля 2020

Идея

Вы задаете размерность элементов контейнера за 2 прохода.

Проход 1:
Установите ширину Элемент контейнера к значению, так что желаемое количество элементов шаблона будет просто соответствовать горизонтально. Это будет 80 для первых двух случаев и 100 для последнего.

Пропуск 2. Масштабирование элементов контейнера по горизонтали до фактической ширины цели (80, 90, 95).

В В приведенном ниже примере кода атрибут transform определяет масштабирование. Обратите внимание, что глаголы translate сначала смещают позицию элемента в начало координат до применения масштабирования и затем переводят перевод обратно (глаголы внутри атрибута `translate оцениваются справа налево).

Коэффициент масштабирования x является отношением целевой ширины и указанной ширины, y просто оставляет высоту такой, какая она есть.

Образец SVG

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="8cm" height="4cm" viewBox="0 0 800 500" version="1.1"
     xmlns="http://www.w3.org/2000/svg">
    <defs>
        <pattern id="circlePattern" patternUnits="userSpaceOnUse"
             x="0" y="0" width="20" height="20"
        >
            <circle cx="10" cy="10" r="10" fill="black" stroke="black" stroke-width="0"/>
        </pattern> 
    </defs>

    <!-- 1. base case 80 px width -->
    <rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
           x="100" y="200" width="80" height="20"
    />

    <!-- 2. scale width to 90px -->
    <rect fill="url(#circlePattern)" stroke="white" stroke-width="0" 
           x="100" y="300" width="80" height="20"
           transform="translate(100, 300) scale (1.125, 1.0) translate(-100, -300)"
    />

    <!-- 3. scale width to 95px -->
    <rect fill="url(#circlePattern)" stroke="white" stroke-width="0" 
           x="100" y="400" width="100" height="20"
           transform="translate(100, 400) scale (0.95, 1.0) translate(-100, -400)"
    />
</svg>

Inline Sample

SVG-части, относящиеся к вопросу, такие же, как и выше.

.showcase {
  /*  background-image: url('#glyph');
    background-size:100% 100%;*/
    filter: url(#embedded);
}
.showcase:before {
   display:block;
   content:'';
   color:transparent;
}
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
   "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="embedded" width="16cm" height="8cm" viewBox="0 0 800 500" version="1.1"
    xmlns="http://www.w3.org/2000/svg"
>
    <defs>
        <pattern id="circlePattern" patternUnits="userSpaceOnUse"
            x="0" y="0" width="20" height="20"
        >
            <circle cx="10" cy="10" r="10" fill="black" stroke="black" stroke-width="0"/>
        </pattern> 
    </defs>

    <!-- 1. base case 80 px width -->
    <rect fill="url(#circlePattern)" stroke="white" stroke-width="0"
        x="100" y="200" width="80" height="20"
    />

    <!-- 2. scale width to 90px -->
    <rect fill="url(#circlePattern)" stroke="white" stroke-width="0" 
         x="100" y="300" width="80" height="20"
         transform="translate(100, 300) scale (1.125, 1.0) translate(-100, -300)"
    />

    <!-- 3. scale width to 95px -->
    <rect fill="url(#circlePattern)" stroke="white" stroke-width="0" 
         x="100" y="400" width="100" height="20"
         transform="translate(100, 400) scale (0.95, 1.0) translate(-100, -400)"
    />
</svg>
<div id="showcase"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...