javascripthtmljquerycssslide

How can I prevent div from shaking when I click fast?


My code is:

$(function() {
  const fullSection = $(".fullsection");
  const container = $("#container");

  // closed fullSection => height:0%();
  $(".fullsection").each(function(index, item) {
    if (!$(item).hasClass("active")) {
      $(item).animate({
        height: "0%",
      });
    }
  });

  // opened fullSection => height:100%();
  var i = 500;
  $(".fullsection").each(function(index, item) {
    if (!$(item).hasClass("active")) {
      $(item).animate({
        height: "100%",
      }, i);
      //console.log(item);
      //console.log(i);
      i += 150;
    }
    // console.log(fullSectionInactive);
  });

  var sum = 0;
  $(fullSection).click(function(event) {
    var functionCompleted = false;
    var chosenWidth = $(this).css("width");
    var chosenWidthNum = parseInt($(this).css("width"));
    var widthactive = parseInt($(this).siblings(".active").css("width"));
    var widthInactive = parseInt(!$(this).siblings(".active").css("width"));
    // Check if there are any opened section
    // if so, closing.
    $(this).siblings().each(function(index, item) {
      var eachWidthNum = parseInt($(this).css("width"));
      if (Math.floor(eachWidthNum) == Math.floor(widthactive)) {
        $(item).removeClass("active");
      }
    });
    // and the clicked element expands
    // if(){
    $(this).addClass("active");
    // }
  });
});
/* reset */

@import url("reset.css");

/* font-family: 'Abril Fatface', cursive; */


/* 400 only */

@import url('https://fonts.googleapis.com/css2?family=Abril+Fatface&display=swap');

/* global class */

body, html {
  width: 100%;
  height: 100%;
}

#container {
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
}

.fullsection {
  width: 5%;
  height: 100%;
  padding: 100px, 0;
  box-sizing: border-box;
  float: left;
  transition: width .3s ease-in-out;
  /* opacity: 0; */
}

.active {
  width: 85%;
}

.section_1 {
  background-color: tomato;
}

.section_2 {
  background-color: teal;
}

.section_3 {
  background-color: cornflowerblue;
}

.section_4 {
  background-color: slateblue;
}
<div id="container">
  <div class="fullsection section_1 active"></div>
  <div class="fullsection section_2"></div>
  <div class="fullsection section_3"></div>
  <div class="fullsection section_4"></div>
</div>
<script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>

i am making a page with only js (jquery) and faced a challenge. its works fine when I click each div (.fullSection) in slow tempo. However once I click each div with relatively fast tempo, suddenly divs (mainly fourth one) jerks and shakes.

I add/remove class name in order to change the width, instead of using animate(); (don't know why but it jerks pretty hard)

I want to prevent users from clicking while the div is still in changing width. or whatever that could stop those divs from jerking and shaking..

I have tried is.("animating") using return false

I want to prevent users from clicking while the div is still in changing width. or whatever that could stop those divs from jerking and shaking.


Solution

  • If you use ontransitionend, you can detect when an animation has finished and work with states to allow a new animation to take place. Maybe this solves it for you.

    $(this).on('transitionend', function(){
        isAnimating = true
     });
    

    $(function() {
        const fullSection = $(".fullsection"),
            container = $("#container"),
            timingStep = 150;
        
        // use state
        let canWeAnimate = true;
    
        fullSection.not(".active").animate({ height: "0%" });
    
        fullSection.each(function(index, item) {
            if (!$(item).hasClass("active")) {
                $(item).animate({ height: "100%" }, index * timingStep + 500);
            }
        });
    
        fullSection.click(function() {
            // check if we can animate
            if (!canWeAnimate || $(this).hasClass("active")) return;
    
            const _this = $(this);
            // set state to false to prevent animations
            canWeAnimate = false;
    
            _this.siblings(".active").removeClass("active");
            _this.addClass("active");
    
            _this.on("transitionend", () => {
                // set state to true to allow animations again
                canWeAnimate = true;
            });
        });
    });
    /* reset */
    
    @import url("reset.css");
    
    /* font-family: 'Abril Fatface', cursive; */
    
    
    /* 400 only */
    
    @import url('https://fonts.googleapis.com/css2?family=Abril+Fatface&display=swap');
    
    /* global class */
    
    body, html {
      width: 100%;
      height: 100%;
    }
    
    #container {
      width: 100%;
      height: 100%;
      -webkit-backface-visibility: hidden;
    }
    
    .fullsection {
      width: 5%;
      height: 100%;
      padding: 100px, 0;
      box-sizing: border-box;
      float: left;
      transition: width .3s ease-in-out;
      /* opacity: 0; */
    }
    
    .active {
      width: 85%;
    }
    
    .section_1 {
      background-color: tomato;
    }
    
    .section_2 {
      background-color: teal;
    }
    
    .section_3 {
      background-color: cornflowerblue;
    }
    
    .section_4 {
      background-color: slateblue;
    }
    <div id="container">
      <div class="fullsection section_1 active"></div>
      <div class="fullsection section_2"></div>
      <div class="fullsection section_3"></div>
      <div class="fullsection section_4"></div>
    </div>
    <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>