Vanilla JS左右切换动画

时间:2018-12-30 16:34:23

标签: javascript css animation

我是编码的新手,正在学习香草JS。我用从左到右移动的圆创建了抽屉导航,但是有一个问题。我在此处上传了当前状态:http://setup.industries/masquarade/

让我陷入困境的问题:

  • 第一次单击汉堡导航图标不会打开抽屉,并且会切换动画。我怀疑问题出在if(open)上,因为open var不能真正用open = header.style.width == '0%'捕获切换状态。初始错误后,它可以正常工作。对我来说真是个头上的划痕。

如果您有其他技巧来获得更好的代码,或者指出我的不良做法,我将很高兴学习。

-

编辑1:我已将完整代码添加到此问题。我不确定如何使椭圆可见,我直接链接到托管网址。

      // 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.log('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>

2 个答案:

答案 0 :(得分:1)

element.style的值是使用javascript或内联样式属性设置的,css不会为您设置该值。因此,如果您使用css设置标题的宽度样式,则header.style.width的值最初将是一个空字符串,从而使表达式header.style.width == '0%'变得虚假。

您可以添加console.log(document.getElementById('header').style.width)来自己检查该值。

因此,第一次单击汉堡包时,条件中的else块将始终运行。

第一次单击汉堡包后,现在通过JavaScript设置了document.getElementById('header').style.width,因此后续的点击操作将达到预期的效果。

要解决此问题,您可以使用内联样式属性来设置标头的宽度,也可以使用javascript使用

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

答案 1 :(得分:1)

您的开放逻辑相反。只需更改100%/ 0%的顺序即可解决此问题。

改进提示:

  1. 使用类而不是实际的CSS检查元素状态。 (在元素打开时将open类添加到元素,而在元素未打开时将其删除)
  2. 通过上述操作,您可以将宽度的操作移至CSS类openheader.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>