Морфинг иконки внутри кнопки svg

258
14 марта 2018, 04:33

Интересно было бы использовать тему плавного морфинга, то есть изменения контуров одной фигуры в контуры другой фигуры в svg кнопках.
Дизайн следующий. В начальном состоянии кнопка имеет иконку - желтая звездочка слева и надпись "Сохранить"

При нажатии на кнопку происходит плавный морфинг звездочки в зеленый чекбокс и надпись "Сохранить" меняется на надпись "Сохранено!"

Понятно, что плавный морфинг достигается изменением координат узловых точек одной фигуры на координаты узловых точек другой фигуры. Я знаю, что для реализации этого должно быть выполнено главное условие - количество узловых точек в обоих фигурах должно быть одинаковым. И пути (патчи) не должны иметь разрывов.

Пример иконки звёздочки

<svg width="194.6" height="185.1" viewBox="0 0 194.6 185.1"> 
  <path fill="#FFD41D" d="M97.3,0 127.4,60.9 194.6,70.7 145.9,118.1 157.4,185.1 97.3,153.5 37.2,185.1 48.6,118.1 0,70.7 67.2,60.9"/> 
</svg>

Пример иконки чекбокса

<svg width="194.6" height="185.1" viewBox="0 0 194.6 185.1">  
  <path d="M110,58.2 147.3,0 192.1,29 141.7,105.1 118.7,139.8 88.8,185.1 46.1,156.5 0,125 23.5,86.6  
  	71.1,116.7" fill="yellowgreen"/>  
</svg>

Это учебный пример. Приветствуется любое количество ответов, все рабочие ответы будут отмечены, даже при несовсем полном выполнении условий.
Может быть применена любая техника реализации с использованием SVG, CSS, JS

Answer 1

Пример морфинга иконки звездочки в чекбокс

<svg width="194.6" height="185.1" viewBox="0 0 194.6 185.1"> 
  <path fill="#FFD41D" d="M97.3,0 127.4,60.9 194.6,70.7 145.9,118.1 157.4,185.1 97.3,153.5 37.2,185.1 48.6,118.1 0,70.7 67.2,60.9"> 
    <animate id="anCheck" begin="click" fill="freeze" attributeName="d" dur="1s" from="M97.3,0 127.4,60.9 194.6,70.7 145.9,118.1 157.4,185.1 97.3,153.5 37.2,185.1 48.6,118.1 0,70.7 67.2,60.9"  to="M110,58.2 147.3,0 192.1,29 141.7,105.1 118.7,139.8 88.8,185.1 46.1,156.5 0,125 23.5,86.6  71.1,116.7"/> 
    <animate id="anGreen" begin="anCheck.end" fill="freeze" attributeName="fill" dur="500ms" to="#53B848"></animate> 
  </path>  
</svg>

Анимация достигается плавным изменением координат узловых точек, которые находятся в атрибуте "d" патча.

Анимация изменения цвета выполняет команда:

<animate id="anGreen" begin="anCheck.end" fill="freeze" attributeName="fill" dur="500ms" to="#53B848"></animate>   

Осталось написать правила CSS для стилизации кнопки и JS скрипт для переключения состояний кнопки путем добавления, удаления классов и запуска анимаций.

var icon = document.getElementById("button"), 
  buttonText = document.getElementById("btnText"), 
  animationToStar = document.getElementById("anStar"), 
  animationToCheck = document.getElementById("anCheck"), 
  animationToYellow = document.getElementById("anYellow"), 
  animationToGreen = document.getElementById("anGreen"); 
 
button.addEventListener('click', function() { 
 
  if (button.classList.contains("keep")) { 
    button.classList.remove("keep"); 
    animationToStar.beginElement(); 
    animationToYellow.beginElement(); 
    buttonText.innerHTML = "Сохранить"; 
  } else { 
    buttonText.innerHTML = "Сохранено!"; 
    button.classList.add("keep"); 
    animationToCheck.beginElement(); 
    animationToGreen.beginElement(); 
 
  } 
 
}, false);
button { 
  border: 0; 
  background: -webkit-linear-gradient( top, #444, #111); 
  background: linear-gradient( to bottom, #444, #111); 
  border-radius: 20px; 
  padding: 10px 30px 12px; 
  outline: 0; 
  display: inline-block; 
  width: 235px; 
  text-align: left; 
} 
 
button:hover, 
button:active { 
  background: black; 
} 
 
button svg { 
  width: 40px; 
  height: 40px; 
  display: inline-block; 
  vertical-align: middle; 
  margin-right: 10px; 
} 
 
button span { 
  font-size: 22px; 
  position: relative; 
  top: 4px; 
  color: white; 
} 
 
body { 
  padding: 20px; 
  text-align: center; 
}
<button id="button"> 
<svg viewBox="0 0 194.6 185.1"> 
  <polygon fill="#FFD41D" points="97.3,0 127.4,60.9 194.6,70.7 145.9,118.1 157.4,185.1 97.3,153.5 37.2,185.1 48.6,118.1 0,70.7  
  	67.2,60.9"> 
    <animate id="anCheck" begin="indefinite" fill="freeze" attributeName="points" dur="500ms" to="110,58.2 147.3,0 192.1,29 141.7,105.1 118.7,139.8 88.8,185.1 46.1,156.5 0,125 23.5,86.6  
  	71.1,116.7"/> 
    <animate id="anGreen" begin="indefinite" fill="freeze" attributeName="fill" dur="500ms" to="#53B848"></animate> 
    <animate id="anStar" begin="indefinite" fill="freeze" attributeName="points" dur="500ms" to="97.3,0 127.4,60.9 194.6,70.7 145.9,118.1 157.4,185.1 97.3,153.5 37.2,185.1 48.6,118.1 0,70.7  
  	67.2,60.9"/> 
    <animate id="anYellow" begin="indefinite" fill="freeze" attributeName="fill" dur="500ms" to="#FFD41D"></animate> 
  </polygon> 
</svg> 
<span id="btnText">Сохранить</span> 
</button>

READ ALSO
Не могу сделать Scroolspy

Не могу сделать Scroolspy

Подскажите, пожалуйста, что не так я делаю для scrollspy?

213
Появляется огромная белая полоса с Bootstrap4

Появляется огромная белая полоса с Bootstrap4

Привет!Я начал делать адаптив для сайта и заметил что начала появлятся огромная белая полоса справа(видно на скриншоте)С чем это связано...

239
css vs svg для создания простых изображений

css vs svg для создания простых изображений

На странице требуется создать несколько (не больше сотни точно, скорее десяток) интерактивных рисунков (надписи и некоторые элементы могут...

242