Vanilla JS слева направо переключает анимацию

Я новичок в программировании и изучаю ванильный JS. Я создал эту навигацию по ящику с кругом, который перемещается слева направо, но есть проблема. Я загрузил текущее состояние сюда: http://setup.industries/masquarade/

Проблема, в которой я застрял:

  • Первый щелчок по значку навигации гамбургера не открывает ящик, и анимация переключается. Я подозреваю, что проблема заключается в if (open), поскольку open var действительно не фиксирует состояние переключения с open = header.style.width == '0%'. После первоначальной ошибки он работает нормально. Настоящая чесалка для меня.

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

-

Изменить 1: я добавил полный код к этому вопросу. Я не уверен, как сделать эллипс видимым, я связался напрямую с размещенным URL.

      // open sidenav //

      function openNav() {
        let header = document.getElementById("header");
        let open = header.style.width == '0%'
        let width = document.body.clientWidth;
        var ellipse = document.getElementById("ellipse");

        function moveEllipseRight() {
          ellipse.animate([
          // keyframes
          { transform: 'translateX(0px)' },
          { transform:  'translateX('+ width + 'px)' }
        ], {
          // timing options
          duration: 500,
          iterations: 1,
          easing: 'ease-in-out',
          fill: 'forwards'
        });}

        function moveEllipseLeft() {
          ellipse.animate([
          // keyframes
          { transform:  'translateX('+ width + 'px)' },
          { transform: 'translateX(0px)' }
        ], {
          // timing options
          duration: 500,
          iterations: 1,
          easing: 'ease-in-out',
          fill: 'forwards'
        });}

        // open sidenav //

        if (open) {
            header.style.width = "100%";
             moveEllipseRight();
        } else {
             header.style.width = '0%';
             moveEllipseLeft();
           }
         }

//  if (open) {
//   ellipse.classList.remove("ellipse_left");
//    ellipse.classList.add("ellipse_right");
//  } else {
//    ellipse.classList.remove("ellipse_right");
//    ellipse.classList.add("ellipse_left");
//  }

//  let ellipse = document.getElementById("ellipse");
//  let pos = 0;
//  let id = setInterval(frame, 5);


 //  function myMove() {
 //    console.info('Hello')
 //    var ellipse = document.getElementById("ellipse");
 //    var pos = -200;
 //    var id = setInterval(frame, 1);
 //    let width = document.body.clientWidth; // - $('#mydiv').width();
 //
 //        function frame() {
 //          if (pos == width - 200) {
 //            clearInterval(id);
 //          } else {
 //            pos++;
 //            ellipse.style.left = pos + "px";
 //          }
 //        }
 //    }


// information tabs //

function openTab(evt, tab) {
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }
  document.getElementById(tab).style.display = "block";
  evt.currentTarget.className += " active";
}
html, body {
    max-width: 100%;
    overflow-x: hidden;
}
body {
    background: black;
    color: white;
    font-family: 'Helvetica Neue', sans-serif;
    font-size: 1.2em;
    line-height: 1.4em;
}

a {
  color: white;
}

.clear {
  clear: both; float: none; height: 40px;
}

/* Ellipse */

#ellipse {
  position: absolute;
  top: 120px;
  z-index:99;
  animation: 3s linear 0s slide 1;
  left: -200px;
}

/*
.ellipse_left {left: -200px;}
.ellipse_right {right: -200px;}
*/


/* Masquarede Logo */

img.masquarade_events {
  opacity: 0.3;
  position: absolute;
  bottom: 20px;
  right: 20px;
}

img.masquarade_events:hover {
  opacity: 0.9;
}


/* Content */

.content {
  margin: 150px 0 0 300px;
  width: 700px;
  height: 400px;
}

@media screen and (max-width: 992px) {
  .content {
    margin: 150px 0 0 0;
    width: 700px;
    height: 400px;
  }
}

.date {
  font-weight: bold;
  margin-bottom: -10px;
}

.location {
}

ul.lineup {
  list-style-position: inside;
  padding: 0;
  list-style-type: none;
  width: 100%
  overflow: hidden;
  margin-bottom: 100px;
}

ul.lineup li {
  margin-right: 50px;
  line-height: 2.5em;
  float: left;
}


/* Buttons */

a.button {
  margin-right: 10px;
  padding: 10px 50px 10px 50px;
  text-decoration: none;
  border-radius: 200px;
  font-size: 0.7em;
  transition: 0.3s;
}

a.white {
  background: white;
  color: black;
}

a.white:hover {
  color: white;
  background: #D90E46;
}

a.black {
  border: 2px white solid;
  color: white;
}

a.black:hover {
  border: 2px #FCF454 solid;
  color: #FCF454;
}

/* Header  */

header {
  position: absolute;
  background-color: black;
  top:0;
  left:0;
  width: 0;
  height: 100%;
  z-index: 1;
}

/* Navigation  */

header nav {
  position: absolute;
  top: 100px;
  right:300px;
}

nav ul {
  list-style-position: inside;
  width: 400px;
  padding: 0;
  list-style-type: none;
  font-size: 1em;
}

nav ul li{
  border-bottom: 1px solid white;
  padding: 10px 0 10px 0;
}

nav ul li:hover{
  font-weight: bold;
  padding: 10px 0 10px 10px;
}

li.active {
  font-weight: bold;
}

nav ul li:first-child{
/*  border-top: 1px solid white;*/
}

nav ul li a{
  text-decoration: none;
}

nav ul h2{
  margin-bottom: 10px;
}

.tabcontent {
  display: none;
}

/* Header Icon */

img.icon {
  position: absolute;
  z-index: 999;
  top:60px;
  right:70px;
}

/* Display */

.display {
  width: 400px;
  height: 400px;
  position: absolute;
  top: 100px;
  right:750px;
}

.display p {
  margin:0 30px 30px 0;
}
<!doctype html>
<html lang = "en">
  <head>
    <!-- SETUP Industries - FUNCTIONAL DESIGN -->
    <meta charset = "utf-8">
    <meta name = "viewport" content = "width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- <link rel = "shortcut icon" type = "image/png" href = "favicon.png"/> -->


    <!-- CSS -->
    <link rel = "stylesheet" type = "text/css" href = "assets/style.css" />
	  <link href = "https://fonts.googleapis.com/css?family=Heebo:400,700,900" rel = "stylesheet">

    <!-- JS -->
    <script src = "assets/javascript.js"></script>


    <title>Masquarade Classix 2019</title>
  </head>
  <body>

  <!-- Navigation -->

    <!-- Icon -->
    <img onclick = "openNav()"id = "icon" src = "http://setup.industries/masquarade/assets/icon.svg" class = "icon" width = "40" alt = "Expand Navigation" />
    <header id = "header">

      <nav>
        <ul>
          <h2>Information</h2>
          <li class = "tablinks" onmouseover = "openTab(event, 'Tickets')"><a href = "#">Tickets and pricing </a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Location')"><a href = "#">Location</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Transportation')"><a href = "#">Transportation</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Amenities')"><a href = "#">Ameneties</li>
          <li class = "tablinks" onmouseover = "openTab(event, 'HouseRules')"><a href = "#">House rules</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'TermsAndConditions')"><a href = "#">Terms and conditions</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Contact')"><a href = "#">Contact</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Partners')"><a href = "#">Partners</a></li>
        </ul>
      </nav>


<div class = "display">


      <div id = "Tickets" class = "tabcontent">
          <h2>Tickets and pricing</h2>
          <p>Saturday day tickets cost 45 EUR incl. service costs and 21% BTW. You can buy tickets online via the button below or at one of the resellers listed below.</p>
          <a href = "#" class = "button white">Buy Tickets</a>
          <br><br>
          <p style = "font-size:0.8em;"> <strong>Paperpoint</strong><br>
            3930 Hamont-achel<br><br>
            <strong>Dag en nachtwinkel </strong><br>
            3900 Overpelt<br><br>
            <strong>VDM bvba, Q8 tankstation</strong> <br>
            Peer<br><br>
            <strong>Frituur De Kromme Draai</strong> <br>
            Eksel<br><br>
            <strong>’t frituurke</strong> <br>
            Haag 22, 3910 Achel<br></p>
      </div>

      <div id = "Location" class = "tabcontent">
          <h2>Location</h2>
      </div>

      <div id = "Transportation" class = "tabcontent">
          <h2>Transportation</h2>
      </div>

      <div id = "Amenities" class = "tabcontent">
          <h2>Amenities</h2>
      </div>

      <div id = "HouseRules" class = "tabcontent">
          <h2>House Rules</h2>
      </div>

      <div id = "TermsAndConditions" class = "tabcontent">
          <h2>Terms And Conditions</h2>
      </div>

      <div id = "Contact" class = "tabcontent">
          <h2>Contact</h2>
      </div>

      <div id = "Partners" class = "tabcontent">
          <h2>Partners</h2>
      </div>



</div>


    </header>
  <!-- Navigation End -->
<div class = "container">
    <div id = "ellipse" class = "ellipse_left">
      <img src = "assets/ellipse.svg" alt = "ellipse" width = "400" height = "400"/>
    </div>
    <img class = "masquarade_events" src = "assets/masquarade_events.png" alt = "Masquarade Events" width = "125" height = ""/>
<div class = "content">

    <p class = "date">25 mei 2019</p>
    <p class = "location">Hennemeeuwis Neerpelt</p>
    <h1>Masquarade Classix </h1>
    <ul class = "lineup">
        <li>Nina Kraviz</li>
        <li>Recondite</li>
        <li>Mind Against</li>
        <li>Âme</li>
        <li>Vince Watson</li>
        <li>Kölsch</li>
        <li>Rodriguez Jr. </li>
        <li></li>
    </ul>
<div class = "clear"></div>

    <a href = "#" class = "button white">Buy Tickets</a>
    <a href = "#" class = "button black">More Information</a>

</div>
</div>

  </body>
</html>

Добавьте в вопрос свой полный код, включая HTML и CSS.

Jack Bashford 30.12.2018 17:38

У вас есть проблема с обещанием, анимация всегда асинхронная

Mister Jojo 30.12.2018 18:01

@FZs onclick = "openNav ()" на значке гамбургерного меню.

Saro Verhees 30.12.2018 18:02

Вместо того, чтобы проверять, соответствует ли ширина 0%, я бы просто добавил к элементу класс «open». Затем проверьте, включены ли классы элемента open

Sølve Tornøe 30.12.2018 18:05
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
4
992
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Значение element.style устанавливается с помощью атрибута javascript или встроенного стиля, css не устанавливает значение за вас. Следовательно, если вы используете CSS для стилизации ширины заголовка, значение для header.style.width изначально будет пустой строкой, что делает выражение header.style.width == '0%' ложным.

Вы можете добавить console.info(document.getElementById('header').style.width), чтобы проверить значение самостоятельно.

В результате при первом щелчке по гамбургеру всегда будет запущен блок else в условном выражении.

После первого щелчка по гамбургеру document.getElementById('header').style.width теперь настраивается через javascript, поэтому последующие щелчки будут вести себя так, как ожидалось.

Чтобы решить эту проблему, вы можете либо использовать встроенный атрибут стиля для стилизации ширины вашего заголовка, либо вы можете получить стиль, используя javascript с

const headerWidth = getComputedStyle(document.getElementById('header')).width;
const open = headerWidth === '0px' || headerWidth === '0%';

Ваша открытая логика перевернулась. Простое изменение порядка 100% / 0% исправляет это.

Советы по улучшению:

  1. проверка состояния элементов с использованием класса вместо фактического CSS. (Добавление класса open к элементу, когда он открыт, и удаление его, когда он не открыт)
  2. Сделав это, вы можете перенести манипуляции с шириной в CSS-класс open: header.open {width: 100%}.
  3. Используя "` "и инкапсулируя свои переменные в ${}, вы можете избавиться от многих" + "следующим образом: {transform:` translateX ($ {width} px) `}

Можно увидеть во фрагменте:

// open sidenav //

      function openNav() {
        let header = document.getElementById("header");
        let open = header.className.includes('open')
        let width = document.body.clientWidth;
        var ellipse = document.getElementById("ellipse");

        function moveEllipseRight() {
          ellipse.animate([
          // keyframes
          { transform: 'translateX(0)' },
          { transform:  `translateX(${width}px)` }
        ], {
          // timing options
          duration: 500,
          iterations: 1,
          easing: 'ease-in-out',
          fill: 'forwards'
        });}

        function moveEllipseLeft() {
          ellipse.animate([
          // keyframes
          { transform:  `translateX(${width}px)` },
          { transform: 'translateX(0)' }
        ], {
          // timing options
          duration: 500,
          iterations: 1,
          easing: 'ease-in-out',
          fill: 'forwards'
        });}

        // open sidenav //

        if (open) {
             moveEllipseLeft();
             header.classList.remove("open");
        } else {
             moveEllipseRight();
             header.classList.add("open");
           }
         }


// information tabs //

function openTab(evt, tab) {
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }
  document.getElementById(tab).style.display = "block";
  evt.currentTarget.className += " active";
}
html, body {
    max-width: 100%;
    overflow-x: hidden;
}
body {
    background: black;
    color: white;
    font-family: 'Helvetica Neue', sans-serif;
    font-size: 1.2em;
    line-height: 1.4em;
}

a {
  color: white;
}

.clear {
  clear: both; float: none; height: 40px;
}

/* Ellipse */

#ellipse {
  position: absolute;
  top: 120px;
  z-index:99;
  animation: 3s linear 0s slide 1;
  left: -200px;
}

/*
.ellipse_left {left: -200px;}
.ellipse_right {right: -200px;}
*/


/* Masquarede Logo */

img.masquarade_events {
  opacity: 0.3;
  position: absolute;
  bottom: 20px;
  right: 20px;
}

img.masquarade_events:hover {
  opacity: 0.9;
}


/* Content */

.content {
  margin: 150px 0 0 300px;
  width: 700px;
  height: 400px;
}

@media screen and (max-width: 992px) {
  .content {
    margin: 150px 0 0 0;
    width: 700px;
    height: 400px;
  }
}

.date {
  font-weight: bold;
  margin-bottom: -10px;
}

.location {
}

ul.lineup {
  list-style-position: inside;
  padding: 0;
  list-style-type: none;
  width: 100%
  overflow: hidden;
  margin-bottom: 100px;
}

ul.lineup li {
  margin-right: 50px;
  line-height: 2.5em;
  float: left;
}


/* Buttons */

a.button {
  margin-right: 10px;
  padding: 10px 50px 10px 50px;
  text-decoration: none;
  border-radius: 200px;
  font-size: 0.7em;
  transition: 0.3s;
}

a.white {
  background: white;
  color: black;
}

a.white:hover {
  color: white;
  background: #D90E46;
}

a.black {
  border: 2px white solid;
  color: white;
}

a.black:hover {
  border: 2px #FCF454 solid;
  color: #FCF454;
}

/* Header  */

header {
  position: absolute;
  background-color: black;
  top:0;
  left:0;
  width: 0;
  height: 100%;
  z-index: 1;
}
/* Header animation css  */
header.open {
  width: 100%;
}

/* Navigation  */

header nav {
  position: absolute;
  top: 100px;
  right:300px;
}

nav ul {
  list-style-position: inside;
  width: 400px;
  padding: 0;
  list-style-type: none;
  font-size: 1em;
}

nav ul li{
  border-bottom: 1px solid white;
  padding: 10px 0 10px 0;
}

nav ul li:hover{
  font-weight: bold;
  padding: 10px 0 10px 10px;
}

li.active {
  font-weight: bold;
}

nav ul li:first-child{
/*  border-top: 1px solid white;*/
}

nav ul li a{
  text-decoration: none;
}

nav ul h2{
  margin-bottom: 10px;
}

.tabcontent {
  display: none;
}

/* Header Icon */

img.icon {
  position: absolute;
  z-index: 999;
  top:60px;
  right:70px;
}

/* Display */

.display {
  width: 400px;
  height: 400px;
  position: absolute;
  top: 100px;
  right:750px;
}

.display p {
  margin:0 30px 30px 0;
}
<!doctype html>
<html lang = "en">
  <head>
    <!-- SETUP Industries - FUNCTIONAL DESIGN -->
    <meta charset = "utf-8">
    <meta name = "viewport" content = "width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- <link rel = "shortcut icon" type = "image/png" href = "favicon.png"/> -->


    <!-- CSS -->
    <link rel = "stylesheet" type = "text/css" href = "assets/style.css" />
	  <link href = "https://fonts.googleapis.com/css?family=Heebo:400,700,900" rel = "stylesheet">

    <!-- JS -->
    <script src = "assets/javascript.js"></script>


    <title>Masquarade Classix 2019</title>
  </head>
  <body>

  <!-- Navigation -->

    <!-- Icon -->
    <img onclick = "openNav()"id = "icon" src = "http://setup.industries/masquarade/assets/icon.svg" class = "icon" width = "40" alt = "Expand Navigation" />
    <header id = "header">

      <nav>
        <ul>
          <h2>Information</h2>
          <li class = "tablinks" onmouseover = "openTab(event, 'Tickets')"><a href = "#">Tickets and pricing </a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Location')"><a href = "#">Location</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Transportation')"><a href = "#">Transportation</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Amenities')"><a href = "#">Ameneties</li>
          <li class = "tablinks" onmouseover = "openTab(event, 'HouseRules')"><a href = "#">House rules</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'TermsAndConditions')"><a href = "#">Terms and conditions</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Contact')"><a href = "#">Contact</a></li>
          <li class = "tablinks" onmouseover = "openTab(event, 'Partners')"><a href = "#">Partners</a></li>
        </ul>
      </nav>


<div class = "display">


      <div id = "Tickets" class = "tabcontent">
          <h2>Tickets and pricing</h2>
          <p>Saturday day tickets cost 45 EUR incl. service costs and 21% BTW. You can buy tickets online via the button below or at one of the resellers listed below.</p>
          <a href = "#" class = "button white">Buy Tickets</a>
          <br><br>
          <p style = "font-size:0.8em;"> <strong>Paperpoint</strong><br>
            3930 Hamont-achel<br><br>
            <strong>Dag en nachtwinkel </strong><br>
            3900 Overpelt<br><br>
            <strong>VDM bvba, Q8 tankstation</strong> <br>
            Peer<br><br>
            <strong>Frituur De Kromme Draai</strong> <br>
            Eksel<br><br>
            <strong>’t frituurke</strong> <br>
            Haag 22, 3910 Achel<br></p>
      </div>

      <div id = "Location" class = "tabcontent">
          <h2>Location</h2>
      </div>

      <div id = "Transportation" class = "tabcontent">
          <h2>Transportation</h2>
      </div>

      <div id = "Amenities" class = "tabcontent">
          <h2>Amenities</h2>
      </div>

      <div id = "HouseRules" class = "tabcontent">
          <h2>House Rules</h2>
      </div>

      <div id = "TermsAndConditions" class = "tabcontent">
          <h2>Terms And Conditions</h2>
      </div>

      <div id = "Contact" class = "tabcontent">
          <h2>Contact</h2>
      </div>

      <div id = "Partners" class = "tabcontent">
          <h2>Partners</h2>
      </div>



</div>


    </header>
  <!-- Navigation End -->
<div class = "container">
    <div id = "ellipse" class = "ellipse_left">
      <img src = "assets/ellipse.svg" alt = "ellipse" width = "400" height = "400"/>
    </div>
    <img class = "masquarade_events" src = "assets/masquarade_events.png" alt = "Masquarade Events" width = "125" height = ""/>
<div class = "content">

    <p class = "date">25 mei 2019</p>
    <p class = "location">Hennemeeuwis Neerpelt</p>
    <h1>Masquarade Classix </h1>
    <ul class = "lineup">
        <li>Nina Kraviz</li>
        <li>Recondite</li>
        <li>Mind Against</li>
        <li>Âme</li>
        <li>Vince Watson</li>
        <li>Kölsch</li>
        <li>Rodriguez Jr. </li>
        <li></li>
    </ul>
<div class = "clear"></div>

    <a href = "#" class = "button white">Buy Tickets</a>
    <a href = "#" class = "button black">More Information</a>

</div>
</div>

  </body>
</html>

Другие вопросы по теме