Страницы

Поиск по вопросам

воскресенье, 22 декабря 2019 г.

Как сделать анимацию кнопки spark?

#javascript #css #css3 #svg #css_animation


Я только что нашел на GitHub Repo, на котором есть отличная анимация для кнопки,
но для Android.   

Вот эта анимация: 

   

Тем не менее, я хочу такую же кнопку для своего сайта, поэтому я начал разрабатывать
это сам.    

Во-первых, я разбил гифку по кадрам. 

И затем по этим кадрам я составил дорожную карту, которой я следую при написании кода:   


Звезда постепенно scale() уменьшается. 
Маленький кружок оранжевого цвета постепенно покрывает звезду при
увеличении.  
Еще один маленький кружок, но на этот раз цвета фона (в данном случае
белый), постепенно перекрывает  предыдущий кружок также увеличением
масштаба.
Наряду с этим звезда также постепенно увеличивается снова и снова
появляясь (таким образом, я должен увеличить z-index), на этот раз
оранжевого цвета (Указывая на ее выбранное состояние).
Есть еще маленькие кружочки, разбросанные со всех сторон новой
звезды.    


Это то, что получилось у меня:    



svg {
  position: absolute;
  top: 0;
  width: 100px;
  height: 100px;
  transition: 0.5s;
  fill:gray;
}

svg:hover {
  animation: up-svg 1s;
  fill: darkorange;
  z-index: 1;
}

svg:hover~.svg {
  animation: up-one 0.5s;
  display: block;
}

svg:hover~.svg1 {
  animation: up-two 1s;
  display: block;
}

.svg {
  position: absolute;
  top: 0;
  border-radius: 50%;
  width: 100px;
  height: 100px;
  background-color: orange;
  display: none;
  transform: scale(0.9);
  transition: 0.5s;
}

.svg1 {
  position: absolute;
  top: 0;
  border-radius: 50%;
  width: 100px;
  height: 100px;
  background-color: white;
  display: none;
  transition: 0.5s;
}

@keyframes up-one {
  0% {
    transform: scale(0);
  }
  40% {
    transform: scale(0);
  }
  100% {
    transform: scale(0.9);
  }
}

@keyframes up-two {
  0% {
    transform: scale(0);
  }
  37.5% {
    transform: scale(0);
  }
  50% {
    transform: scale(0.25);
  }
  62.5% {
    transform: scale(0.5);
  }
  75% {
    transform: scale(0.75);
  }
  87.5% {
    transform: scale(0.9);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes up-svg {
  0% {
    transform: scale(1);
    fill: gray;
    z-index: 0;
  }
  70% {
    transform: scale(0);
    fill: darkorange;
    z-index: 1;
  }
  100% {
    transform: scale(1);
    fill: darkorange;
    z-index: 1;
  }
}

Я пробовал, но все же результат не похож на ожидаемый, и я застрял с этими кругами рассеяния тоже. Цвета не являются приоритетом прямо сейчас. И я придерживаюсь свойства hover (чтобы анимация была видна снова и снова без перезагрузки), пока анимация не будет доведена до конца. Я искал решения в Google и SO, но пока не повезло. Итак, кто-нибудь поможет мне сделать такую анимацию? UPDATE Добавляю ссылку на spark анимацию от известного мастера Ana Tudor


Ответы

Ответ 1



Вот моя не идеальная идея, где я буду полагаться только на CSS и немного элементов. Я подробно опишу каждую часть, а затем объединю это в одну анимацию. Для части с иконкой (звездочкой) я бы сделал то же самое, как у вас, но я, вероятно, рассмотрю фильтр в оттенках серого, чтобы иметь общий эффект, который работает с любым элементом и любым цветом. .magic i{ color:red; filter:grayscale(100%); } .magic:hover i{ animation:change 1s forwards; } @keyframes change{ 50% { transform:scale(0); filter:grayscale(100%); } 51% { filter:grayscale(0%); } 100% { transform:scale(1); filter:grayscale(0%); } } Для круга я рассмотрю только один элемент, и хитрость здесь заключается в том, чтобы полагаться на окраску border по сравнению с окраской background. Мы изначально устанавливаем height/width равной нулю, и у нас есть только border, поэтому это будет полный круг. Затем мы просто уменьшаем толщину border, сохраняя общую ширину одинаковой. Итак, мы сделаем: Начальная форма width/height - 0 and border-width - 0 Мы увеличиваем border-width, чтобы создать эффект увеличения Мы уменьшаем border-width, увеличивая при этом width/height, чтобы сохранить общую width/height одинаковой. .circle { display:inline-block; width:0px; height:0px; border-radius:50%; border-color:orange; border-style:solid; border-width:0px; box-sizing:border-box; } body:hover .circle { animation:change 1s forwards; } @keyframes change { 50% { border-width:25px; } 100% { border-width:0; width:50px; height:50px; } } body { min-height:100px; } Это решение имеет небольшой недостаток, так как элемент будет увеличиваться сверху слева, а не по центру. Мы можем исправить это, используя scale вместо изменения width/height: .circle { display:inline-block; width:50px; height:50px; border-radius:50%; border-color:orange; border-style:solid; border-width:25px; transform:scale(0); box-sizing:border-box; } body:hover .circle { animation:change 1s linear forwards; } @keyframes change { 50% { transform:scale(1); border-width:25px; } 100% { transform:scale(1); border-width:0; } } body { min-height:100px; } Мы можем упростить рассмотрение простого transition: .circle { display:inline-block; width:50px; height:50px; border-radius:50%; border-color:orange; border-style:solid; border-width:25px; transform:scale(0); box-sizing:border-box; transition: transform 0.5s, border-width 0.5s 0.5s; } body:hover .circle { border-width:0; transform:scale(1); } body { min-height:100px; } Теперь сложная часть анимации и добавление маленьких кругов. Для этого я буду полагаться на radial-gradient и scale. Идея состоит в том, чтобы создать маленькие круги с градиентом внутри одного элемента, и используя scale, мы создадим эффект их увеличения и движения. .small { display:inline-block; width:100px; height:100px; background: /*4 reds*/ radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), /*4 oranges*/ radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%); background-size:16px 16px; background-position: calc(50% - 30px) calc(50% - 30px), calc(50% + 30px) calc(50% - 30px), calc(50% - 30px) calc(50% + 30px), calc(50% + 30px) calc(50% + 30px), calc(50% + 0px) calc(50% + 40px), calc(50% + 40px) calc(50% + 0px), calc(50% - 40px) calc(50% + 0px), calc(50% + 0px) calc(50% - 40px); background-repeat:no-repeat; border-radius:50%; } Я создал 8 кругов и разместил их, смещая их от центра (посмотрите этот ответ, чтобы узнать больше о том, как работает background-position: https://stackoverflow.com/a/51734530/8620333 Вам просто нужно настроить размер, положение и цвет круга, как вам необходимо. А вот с анимацией: .small { display:inline-block; width:100px; height:100px; background: /*4 reds*/ radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), /*4 oranges*/ radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%); background-size:16px 16px; background-position: calc(50% - 30px) calc(50% - 30px), calc(50% + 30px) calc(50% - 30px), calc(50% - 30px) calc(50% + 30px), calc(50% + 30px) calc(50% + 30px), calc(50% + 0px) calc(50% + 40px), calc(50% + 40px) calc(50% + 0px), calc(50% - 40px) calc(50% + 0px), calc(50% + 0px) calc(50% - 40px); background-repeat:no-repeat; border-radius:50%; transform:scale(0); transition:transform 0.5s,opacity 0.4s 0.4s; } body { min-height:200px; } body:hover .small { transform:scale(1); opacity:0; } Если вы хотите более точную анимацию, вы также можете уменьшить круги, уменьшив background-size. .small { display:inline-block; width:100px; height:100px; background: /*4 reds*/ radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), /*4 oranges*/ radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%); background-size:16px 16px; /*at least 2x7px */ background-position: calc(50% - 30px) calc(50% - 30px), calc(50% + 30px) calc(50% - 30px), calc(50% - 30px) calc(50% + 30px), calc(50% + 30px) calc(50% + 30px), calc(50% + 0px) calc(50% + 40px), calc(50% + 40px) calc(50% + 0px), calc(50% - 40px) calc(50% + 0px), calc(50% + 0px) calc(50% - 40px); background-repeat:no-repeat; border-radius:50%; transform:scale(0); transition:transform 0.5s,opacity 0.4s 0.4s,background-size 0.5s 0.4s; } body { min-height:200px; } body:hover .small { transform:scale(1); opacity:0; background-size:0 0; } Теперь вы просто делаете то же самое с другими маленькими кружками, изменяя некоторые значения. Давайте соединим все это! .magic { display:inline-block; margin:50px; position:relative; } .magic i{ color:orange; filter:grayscale(100%); position:relative; } .magic:hover i{ animation:change 1s forwards; } @keyframes change{ 50% { transform:scale(0); filter:grayscale(100%); } 51% { filter:grayscale(0%); } 100% { transform:scale(1); filter:grayscale(0%); } } /**/ .magic:before { content:""; position:absolute; top:calc(50% - 45px); left:calc(50% - 45px); width:90px; height:90px; border-radius:50%; border-color:orange; border-style:solid; border-width:45px; transform:scale(0); box-sizing:border-box; } .magic:hover::before { transition: transform 0.5s, border-width 0.5s 0.5s; border-width:0; transform:scale(1); } /**/ .magic::after { content:""; position:absolute; width:160px; height:160px; left:calc(50% - 80px); top:calc(50% - 80px); background: /*4 reds*/ radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), /*4 oranges*/ radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%); background-size:16px 16px; background-position: calc(50% - 50px) calc(50% - 50px), calc(50% + 50px) calc(50% - 50px), calc(50% - 50px) calc(50% + 50px), calc(50% + 50px) calc(50% + 50px), calc(50% + 0px) calc(50% + 70px), calc(50% + 70px) calc(50% + 0px), calc(50% - 70px) calc(50% + 0px), calc(50% + 0px) calc(50% - 70px); background-repeat:no-repeat; border-radius:50%; transform:scale(0); } .magic:hover:after { transform:scale(1); opacity:0; background-size:0 0; transition: transform 0.5s 0.5s, opacity 0.4s 0.9s, background-size 0.5s 0.9s; } Как я уже сказал, он не идеален, но очень близок к тому, что вы хотите, с меньшим количеством элементов и необходимыми деталями, так что вы можете легко настроить различные значения. Я не добавил крошечные круги для простоты, но мы можем рассмотреть другой псевдоэлемент и легко добавить их: .magic { display:inline-block; margin:50px; position:relative; } .magic i{ color:orange; filter:grayscale(100%); } .magic:hover i{ animation:change 1s forwards; } @keyframes change{ 50% { transform:scale(0); filter:grayscale(100%); } 51% { filter:grayscale(0%); } 100% { transform:scale(1); filter:grayscale(0%); } } /**/ .magic:before { content:""; position:absolute; top:calc(50% - 45px); left:calc(50% - 45px); width:90px; height:90px; border-radius:50%; border-color:orange; border-style:solid; border-width:45px; transform:scale(0); box-sizing:border-box; } .magic:hover::before { border-width:0; transform:scale(1); transition: transform 0.5s, border-width 0.5s 0.5s; } /**/ .magic::after, .magic i::after{ content:""; position:absolute; width:160px; height:160px; left:calc(50% - 80px); top:calc(50% - 80px); background: /*4 reds*/ radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), radial-gradient(circle,red 50%,transparent 60%), /*4 oranges*/ radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%), radial-gradient(circle,orange 50%,transparent 60%); background-size:16px 16px; background-position: calc(50% - 50px) calc(50% - 50px), calc(50% + 50px) calc(50% - 50px), calc(50% - 50px) calc(50% + 50px), calc(50% + 50px) calc(50% + 50px), calc(50% + 0px) calc(50% + 70px), calc(50% + 70px) calc(50% + 0px), calc(50% - 70px) calc(50% + 0px), calc(50% + 0px) calc(50% - 70px); background-repeat:no-repeat; border-radius:50%; transform:scale(0); } .magic i::after { background-size:10px 10px; transform:rotate(10deg) scale(0); } .magic:hover:after { transform:scale(1); opacity:0; background-size:0 0; transition:transform 0.5s 0.5s,opacity 0.4s 0.9s,background-size 0.5s 0.9s; } .magic:hover i:after { transform:rotate(10deg) scale(1); opacity:0; background-size:0 0; transition:transform 0.5s 0.5s,opacity 0.4s 0.9s,background-size 0.5s 0.9s; } /**/ UPDATE Вот улучшение кода, учитывающее некоторую переменную CSS и использующее более гибкий модуль для простого управления позиционированием: .magic { display:inline-block; margin:50px; position:relative; --r:45px; } .magic i{ color:orange; filter:grayscale(100%); } .magic:hover i{ animation:change 1s forwards; } @keyframes change{ 50% { transform:scale(0); filter:grayscale(100%); } 51% { filter:grayscale(0%); } 100% { transform:scale(1); filter:grayscale(0%); } } /**/ .magic:before { content:""; position:absolute; top:calc(50% - var(--r)); left:calc(50% - var(--r)); width:calc(2*var(--r)); height:calc(2*var(--r)); border-radius:50%; border:solid orange var(--r); transform:scale(0); box-sizing:border-box; } .magic:hover::before { border-width:0; transform:scale(1); transition: transform 0.5s, border-width 0.5s 0.5s; } /**/ .magic::after, .magic i::after{ content:""; position:absolute; width: calc(4*var(--r)); height:calc(4*var(--r)); left:calc(50% - 2*var(--r)); top: calc(50% - 2*var(--r)); --c1:radial-gradient(circle,red 50% ,transparent 60%); --c2:radial-gradient(circle,orange 50%,transparent 60%); background: /*4 reds*/ var(--c1),var(--c1),var(--c1),var(--c1), /*4 oranges*/ var(--c2),var(--c2),var(--c2),var(--c2); background-size:calc(var(--r)/3) calc(var(--r)/3); background-position: calc(50% - var(--r)) calc(50% - var(--r)), calc(50% + var(--r)) calc(50% - var(--r)), calc(50% - var(--r)) calc(50% + var(--r)), calc(50% + var(--r)) calc(50% + var(--r)), calc(50% + 0px) calc(50% + var(--r)*1.414), calc(50% + var(--r)*1.414) calc(50% + 0px), calc(50% - var(--r)*1.414) calc(50% + 0px), calc(50% + 0px) calc(50% - var(--r)*1.414); background-repeat:no-repeat; transform:scale(0); } .magic i::after { background-size:calc(var(--r)/5) calc(var(--r)/5); transform:rotate(55deg) scale(0); } .magic:hover:after { transform:scale(1); opacity:0; background-size:0 0; transition: transform 0.5s 0.5s, opacity 0.4s 0.9s, background-size 0.5s 0.9s; } .magic:hover i:after { transform:rotate(55deg) scale(1); opacity:0; background-size:0 0; transition: transform 0.5s 0.5s, opacity 0.4s 0.9s, background-size 0.5s 0.9s; } /**/ В основном, переменная r будет определять радиус всей фигуры, и вы можете легко изменить ее в зависимости от размера вашей иконки.

Комментариев нет:

Отправить комментарий