3

Это не перевод, разработка вопроса и ответов авторские. Здесь вы найдёте подробное описание интересных возможностей в использовании и анимировании масок SVG, освоив которые, вы сможете реализовать свой, оригинальный дизайн веб страничек.

Вопрос инспирирован топиком: Круговая маска CSS с переменной шириной границы

В ответе на тот вопрос были использованы правила CSS
А как сделать тоже самое с помощью SVG?

введите сюда описание изображения

Понятно, что нужно использовать маски SVG.

У меня получилось с помощью маски вырезать круг:

<style>
.container {
width:100%;
height:100%;
}
</style>
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
       viewBox="0 0 1400 788" preserveAspectRatio="xMinYMin meet">  
<defs>
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="red" />
    <g fill="white">
       <!-- Круговая маска --> 
    <circle cx="700" cy="392" r="300" />
  </g>
 </mask>
 </defs>

<image xlink:href="https://i.stack.imgur.com/sUiPo.jpg" width="100%" height="100%" mask="url(#msk1)" />

</svg>
</div>

Вопросы

  1. Как сделать маску для более сложной формы?
  2. Как добавить к маске белые сегменты обводки?
  3. Можно ли анимировать маску, обводку окружностей?
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384

2 Answers2

4

Для получения нужной формы добавляем в маску вторую окружность меньшего диаметра

<style>
.container {
width:100%;
height:100%;
}
</style>
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
        viewBox="0 0 1400 788" preserveAspectRatio="xMinYMin meet">  
<defs>
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="red" />
    <g fill="white">
       <!-- Center circle --> 
    <circle cx="700" cy="392" r="300"  />
    <!-- Left circle -->
   <circle cx="520" cy="620" r="120" />
    </g> 
 </mask>
 </defs>

<image xlink:href="https://i.stack.imgur.com/sUiPo.jpg"" width="100%" height="100%" mask="url(#msk1)" />

</svg>
</div>

  • В маске <rect width="100%" height="100%" fill="red" />

прямоугольник перекрывает всё изображение. Красный цвет закраски прямоугольника - fill="red" занимает промежуточное значение между белым цветом, что придаёт маске полную прозрачность и чёрным цветом, который делает маску полностью непрозрачной. Поэтому остальная часть картинки становится полупрозрачной
см. топик Практические примеры применения масок svg

  • Окружности в маске имеют окраску белого цвета, поэтому эта область становится полностью прозрачной.

Создание белых сегментов окружностей

  • Для этого нужно сделать некоторые расчёты:

Длина окружности при радиусе 300px равна: 2 * 3.4115 * 300 = 1884,9px

Нам нужен сектор длиной примерно (визуально по картинке) в одну восьмую часть
1884,9 / 8 = 235.5px

  • Для отрисовки сектора применим атрибут stroke-dasharray

stroke-dasharray="235.5 1648.5", где первый параметр длина черточки, второй параметр длина пробела.

Для второй окружности делаем точно такие же расчеты, но для радиуса 120px

  • Добавляем атрибуты stroke-dasharray к окружностям в маске и закрашиваем обводку в чёрный цвет. Это сделает сегменты непрозрачными, после применения маски сегменты окружности будут белого цвета

Для позиционирования сегмента сдвигаем его начало командой stroke-dashoffset

stroke-dashoffset="400"

Собираем всё вместе:

<style>
.container {
width:100%;
height:100%;
}
</style>
<div class="container">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
        viewBox="0 0 1400 788" preserveAspectRatio="xMinYMin meet">  
<defs>
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="red" />
    <g fill="white">
       <!-- Center circle --> 
    <circle cx="700" cy="392" r="300"  stroke="#151515"  stroke-width="17"  
   stroke-dasharray="235.5 1648.5" stroke-dashoffset="400" />
    <!-- Left circle -->
   <circle cx="520" cy="620" r="120" stroke="#151515"  stroke-width="12"  
   stroke-dasharray="114.245 639.96" stroke-dashoffset="434"  />
    </g> 
 </mask>
 </defs>
 &lt;image xlink:href="https://i.stack.imgur.com/sUiPo.jpg" width="100%" height="100%" mask="url(#msk1)" /&gt; 

</svg>
</div>

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
4

SVG анимации

#1. Вращение сегментов окружности

Применяется команда анимации stroke-dashoffset сдвига начала сегмента.

  • Сначала вращается сегмент малого круга, условие запуска анимации begin="svg1.click" - клик по любой части SVG полотна
  • После окончания первой анимации начинается вращение сегмента большого круга.
    Условие запуска - begin="an2.end"

<style>
.container {
width:100%;
height:100%;
}
</style>
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
        viewBox="0 0 1400 788" preserveAspectRatio="xMinYMin meet">  
<defs>
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="red" />
    <g fill="white">
       <!-- Center circle --> 
    <circle id="circleBig" cx="700" cy="392" r="300"  stroke="#151515"  stroke-width="17"  
       stroke-dasharray="235.5 1648.5" stroke-dashoffset="400" pointer-events="none" >
       <animate id="an1" attributeName="stroke-dashoffset" begin="an2.end" dur="6s" values="400;-1484.8" repeatCount="1"  restart="whenNotActive" />
  </circle>
    <!-- Left circle -->
   <circle cx="520" cy="620" r="120" stroke="#151515"  stroke-width="12"  
        stroke-dasharray="114.245 639.96" stroke-dashoffset="434"  > 
       <animate id="an2" attributeName="stroke-dashoffset" begin="svg1.click" dur="2s" values="434;-320"    repeatCount="2" restart="whenNotActive" />
  </circle>
    </g> 
 </mask>
 </defs>

<image xlink:href="https://i.stack.imgur.com/sUiPo.jpg" width="100%" height="100%" mask="url(#msk1)" /> </svg>
</div>

#2. Вращение малой окружности маски

Координаты вращения малой окружности это координаты центра большой окружности.
Команда анимации вращения :

<animateTransform id="an2T" attributeName="transform" type="rotate" begin="svg1.click" dur="8s" values="0 700 392;-180 700 392;90 700 392;0 700 392"    repeatCount="1" restart="whenNotActive" />

<style>
.container {
width:100%;
height:100%;
}
</style>
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
        viewBox="0 0 1400 888" preserveAspectRatio="xMinYMin meet">  
<defs>
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="red" />
    <g fill="white">
       <!-- Center circle --> 
    <circle id="circleBig" cx="700" cy="392" r="300"  stroke="#151515"  stroke-width="17"  
       stroke-dasharray="235.5 1648.5" stroke-dashoffset="400" pointer-events="none" >
       <animate id="an1" attributeName="stroke-dashoffset" begin="svg1.click" dur="8s" values="400;-1484.8" repeatCount="1"  restart="whenNotActive" />
  </circle> 
    <!-- small circle -->
   <circle cx="520" cy="620" r="120"> 
       <animateTransform id="an2T" attributeName="transform" type="rotate" begin="svg1.click" dur="8s" values="0 700 392;-180 700 392;90 700 392;0 700 392"    repeatCount="1" restart="whenNotActive" />
  </circle>
    </g> 
 </mask>
 </defs>

<image xlink:href="https://i.stack.imgur.com/sUiPo.jpg" width="100%" height="100%" mask="url(#msk1)" />

</svg>
</div>

#3. Увеличение размеров малой окружности

Достигается анимацией изменения радиуса окружности

<animate attributeName="r" begin="svg1.click" dur="8s" values="120;60;120" /> 
           <animate id="an2" attributeName="stroke-dashoffset" begin="svg1.click" dur="1s" values="434;-320"    repeatCount="8" restart="whenNotActive" />

<style>
.container {
width:100%;
height:100%;
}
</style>
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
        viewBox="0 0 1400 888" preserveAspectRatio="xMinYMin meet">  
<defs>
  <mask id="msk1"> 
    <rect width="100%" height="100%" fill="red" />
    <g fill="white">
       <!-- Big circle --> 
    <circle id="circleBig" cx="700" cy="392" r="300"  stroke="#151515"  stroke-width="17"  
       stroke-dasharray="235.5 1648.5" stroke-dashoffset="400" pointer-events="none" >
       <animate id="an1" attributeName="stroke-dashoffset" begin="svg1.click" dur="8s" values="400;-1484.8" repeatCount="1"  restart="whenNotActive" />
  </circle> 
    <!-- Small circle -->
   <circle cx="520" cy="620" r="120" stroke="#151515"  stroke-width="12"  
        stroke-dasharray="114.245 639.96" stroke-dashoffset="434"  >
  &lt;animate attributeName="r" begin="svg1.click" dur="8s" values="120;60;120" /&gt; 
 &lt;animate id="an2" attributeName="stroke-dashoffset" begin="svg1.click" dur="1s" values="434;-320"    repeatCount="8" restart="whenNotActive" /&gt;

</circle> </g> </mask> </defs>

<image xlink:href="https://i.stack.imgur.com/sUiPo.jpg" width="100%" height="100%" mask="url(#msk1)" />

</svg>
</div>

Live Demo

Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384