August 8, 2020

Анимация на ванильном js

Всех приветствую, сегодня хочу рассказать как я сделал первую в своей жизни анимацию на javascript. Думаю можно начинать без лишних слов

Теория

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

Кстати, анимация у нас будет накладываться на hr, расположенный под блоком меню.

Практика

Сейчас я покажу вам верстку, стили и js файл моего меню. Начнем мы с верстки и думаю здесь рассказывать нечего

<nav class="menu" id="menu">
    <ul>
        <li><div class="logo"><a href="/">
            <ul>
                <h1><span class="prog">Prog</span><span class="way">Way</span></h1>
            </ul></a>
        </div></li>
        <li><a onmouseover="animation('soft', 'over')" onmouseout="animation('soft', 'out')" class="amenu" href="/soft">Софт</a><hr class="step0" id="soft"></li>
        <li><a onmouseover="animation('quizs', 'over')" onmouseout="animation('quizs', 'out')" class="amenu" href="/quizs">Задачи</a><hr class="step0" id="quizs"></li>            
        <li><a onmouseover="animation('posts', 'over')" onmouseout="animation('posts', 'out')" class="amenu" href="/posts">Статьи</a><hr class="step0" id="posts"></li>
    </ul>
</nav>

Теперь рассмотрим стили

.menu {
    display: block;    
    width: 100%;    
    padding-bottom: 0;    
    box-shadow: 0px 15px 5px 10px #272933;  
}

ul {
    list-style: none;
    margin: 0% 0%;
}

.menu li {
    padding-top: 1em;
    width: 100%;    
    text-align: center;
}

.menu ul {
    display: flex;      
    background: #18171c;    
    padding-left: 15%;    
    padding-right: 15%;    
    height: 100%;
}

.menu a {
    height: 100%;    
    display: block;    
    color: white;    
    font-weight: bold;    
    background: #18171c;    
    text-decoration: none;    
    font-size: 18px;
}

.menu li {
    width: 15%;    
    padding-left: 4.3%;    
    height: 100%;    
    text-align: center;    
    vertical-align: middle;
}

.amenu {
    padding-top: 4%;    
    font-family: 'Didact Gothic', sans-serif;
}

.prog {
    color: white;    
    font-size: 25px;
}

.way {
    color: #9966cc;    
    font-size: 25px;
}

.step0 {
    width: 0%;
}

.step1 {
    width: 10%;
}

.step2 {
    width: 20%;
}

.step3 {
    width: 30%;
}

.step4 {
    width: 40%;
}

.step5 {
    width: 50%;
}

.step6 {
    width: 60%;
}

.step7 {
    width: 70%;
}
 
.step8 {
     width: 80%;
}
 
.step9 {
    width: 90%;
}

.step10 {
    width: 100%;
}

А сейчас самое интересное... JAVASCRIPT код, но перед этим предлагаю подробнее рассмотреть верстку отдельного элемента меню

<li><a onmouseover="animation('soft', 'over')" onmouseout="animation('soft', 'out')" class="amenu" href="/soft">Софт</a><hr class="step0" id="soft"></li>

Элементу <a> мы задаем функцию animation в аргументы onmouseover и onmouseout. А функция в свою очередь принимает id hr-а( будет нужен для выбора определенного hr ) и over/out( это будет влиять на одно из условий в функции )

Элементу <hr> мы изначально задаем класс step0 и id, в моем случае это "soft".

Теперь перейдем в javascript-файл и изучим код функции

var timerover;
var timerout;
function animation(id, where) {
    var hr = document.getElementById(id)
    if (where == "over"){
        clearInterval(timerout)
        timerover = setInterval(morewidth, 20);
        
        function morewidth(){
            var classnow = hr.className
            if (classnow == "step0"){
                hr.className = "step1"
            } else if (classnow == "step1"){
                hr.className = "step2"
            } else if (classnow == "step2"){
                hr.className = "step3"            
            } else if (classnow == "step3"){
                hr.className = "step4"
            } else if (classnow == "step4"){
                hr.className = "step5"            
            } else if (classnow == "step5"){                
                hr.className = "step6"            
            } else if (classnow == "step6"){                
                hr.className = "step7"            
            } else if (classnow == "step7"){                
                hr.className = "step8"            
            } else if (classnow == "step8"){                
                hr.className = "step9"            
            } else if (classnow == "step9"){                
                hr.className = "step10"                
                clearInterval(timerover)
            }
        }
    } else if (where == "out") {
        clearInterval(timerover)
        timerout = setInterval(lesswidth, 20);
        
        function lesswidth(){
            var classnow = hr.className
            if (classnow == "step10"){
                hr.className = "step9"
            } else if (classnow == "step9"){                
                hr.className = "step8"            
            } else if (classnow == "step8"){                
                hr.className = "step7"            
            } else if (classnow == "step7"){                
                hr.className = "step6"            
            } else if (classnow == "step6"){                
                hr.className = "step5"            
            } else if (classnow == "step5"){                
                hr.className = "step4"            
            } else if (classnow == "step4"){                
                hr.className = "step3"            
            } else if (classnow == "step3"){                
                hr.className = "step2"            
            } else if (classnow == "step2"){                
                hr.className = "step1"            
            } else if (classnow == "step1"){                
                hr.className = "step0"                
                clearInterval(timerout)            
            }
        }    
    } 
}

Давайте по порядку:

  • В самом начале мы создаем 2 переменных: timerover и timerout. Они нам нужны для начала и завершения интервалов.
  • Потом уже в теле функции мы задаем проверку на аргумент "where"( предлагаю изучить первое ответвление, так как второе почти полностью индентично )
  • Здесь мы отчищаем timerout и запусткаем интервал timerover. В аргумент интервала передаем функцию( в данном случае morewidth, и частоту запуска 20мс )
  • Теперь приступим к функции morewidth. Тут мы получаем класс hr на данный момент и проверяем его. При выполнении условия мы меняем его класс, тем самым увеличивая width элемента на 10%. И если доходим до step10 отчищаем интервал.

ВАЖНО

Не забывайте чистить интервал, иначе две функции буду противодействовать друг другу.

Итог

Это один из вариантов реализации анимации, я показал как это сделать именно на ванильном javascript`е. А что у нас получилось можете посмотреть в моем телеграм канале.

На сегодня все,
Удачи, программисты!