菜单动画出现意外延迟

时间:2017-05-16 17:37:11

标签: javascript jquery html css

以下是我正在处理的菜单。由于某种原因它有点不稳定,但更令人担忧的是在它动画之前点击一个项目后的半秒延迟。

基本上,非活动菜单不在右侧的视口(right: -200px)。当您点击任何项目时,它将全部滑动"活动"左边的项目20px和"激活"目标菜单。

我认为这很简单,但我无法弄清楚可能导致延迟和波动的原因。



$('.rmenu').on('click', '.item', function() {
  var targetid = $(this).data('target-id');
  var targetelement = $('#' + targetid);
  console.log('Clicked ' + targetid);
  if ($(this).data('target-type') === 'menu' && !targetelement.hasClass('active')) { //if target is a submenu and it's not already active
    $('.active').animate({
      'right': '+=20px'
    }); //move all "active" menus to the left a bit (stack behind)
    targetelement.addClass('active').animate({
      'right': '0px'
    }); //make new submenu active
  }
});

$('.rmenu').on('click', '.back', function() {
  var parentid = $(this).parent().data('parent-id');
  $(this).parent().parent().removeClass('active').css('right', '-200px');
  $('.active').animate({
    'right': '-=20px'
  });
})

body {
  background-color: darkgray;
  overflow: hidden;
}
#menu {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 300px;
}
.rmenu {
  position: absolute;
  right: -200px;
  bottom: 0;
  width: 200px;
  transition: .2s;
  border: 1px solid gray;
}
.rmenu.active {
  right: 0;
}
.rmenu div {
  background-color: white;
  border-bottom: 1px solid gray;
}
.rmenu div:last-child {
  border: none;
}
.rmenu .title {
  text-align: center;
  padding: 5px;
  color: gray;
}
.rmenu .item {
  padding: 3px;
  cursor: pointer;
}
.rmenu .back {
  padding-right: 5px;
  cursor: pointer;
}
.rmenu .submenu-indicator {
  float: right;
  padding-right: 5px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu">
  <!--main menu-->
  <div id="home" class="rmenu active">
    <div class="title">
      <span>Home</span>
    </div>
    <div data-target-id="items" data-target-type="menu" class="item">
      <span class="label">Items</span><span class="submenu-indicator">></span>
    </div>
    <div class="item">
      <span class="label">Social</span>
    </div>
    <div class="item">
      <span class="label">Settings</span>
    </div>
  </div>

  <!--items menu-->
  <div id="items" class="rmenu" data-parent-id="home">
    <div class="title">
      <span class="back"><</span><span>Items</span>
    </div>
    <div class="item" data-target-id="tables" data-target-type="menu">
      <span class="label">Tables</span><span class="submenu-indicator">></span>
    </div>
    <div class="item">
      <span class="label">Lamps</span>
    </div>
    <div class="item">
      <span class="label">Chairs</span>
    </div>
  </div>

  <!--tables menu-->
  <div id="tables" class="rmenu" data-parent-id="items">
    <div class="title">
      <span class="back"><</span><span>Tables</span>
    </div>
    <div class="item">
      <span class="label">1</span>
    </div>
    <div class="item">
      <span class="label">2</span>
    </div>
    <div class="item">
      <span class="label">3</span>
    </div>
    <div class="item">
      <span class="label">4</span>
    </div>
    <div class="item">
      <span class="label">5</span>
    </div>
    <div class="item">
      <span class="label">6</span>
    </div>
  </div>
</div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

你的CSS :FOO正在与你的jQuery动画作斗争。两者都试图同时为transition属性设置动画,导致一些笨拙的运动。

通过指定要应用于活动的元素的CSS转换,并在启动动画后添加类right ,我已经设法解决了这个问题。

.active
.rmenu:not(.active) {
  transition: .2s;
}

targetelement.animate({
    'right': '0px'
}).addClass("active"); //addClass() moved to AFTER animate()
$('.rmenu').on('click', '.item', function() {
  var targetid = $(this).data('target-id');
  var targetelement = $('#' + targetid);
  console.log('Clicked ' + targetid);
  if ($(this).data('target-type') === 'menu' && !targetelement.hasClass('active')) { //if target is a submenu and it's not already active
    $('.active').animate({
      'right': '+=20px'
    }); //move all "active" menus to the left a bit (stack behind)
    targetelement.animate({
      'right': '0px'
    }).addClass("active"); //make new submenu active
  }
});

$('.rmenu').on('click', '.back', function() {
  var parentid = $(this).parent().data('parent-id');
  $(this).parent().parent().removeClass('active').css('right', '-200px');
  $('.active').animate({
    'right': '-=20px'
  });
})
body {
  background-color: darkgray;
  overflow: hidden;
}

#menu {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 300px;
}

.rmenu {
  position: absolute;
  right: -200px;
  bottom: 0;
  width: 200px;
  border: 1px solid gray;
}

.rmenu:not(.active) {
  transition: .2s;
}

.rmenu.active {
  right: 0;
  background-color: blue;
}

.rmenu div {
  background-color: white;
  border-bottom: 1px solid gray;
}

.rmenu div:last-child {
  border: none;
}

.rmenu .title {
  text-align: center;
  padding: 5px;
  color: gray;
}

.rmenu .item {
  padding: 3px;
  cursor: pointer;
}

.rmenu .back {
  padding-right: 5px;
  cursor: pointer;
}

.rmenu .submenu-indicator {
  float: right;
  padding-right: 5px;
}

答案 1 :(得分:1)

我重写了这一点,根本没有使用$.animate(),也没有引用right,因为它不具备效果。这是使用transition属性上的transform在CSS中完成所有操作的方法。

&#13;
&#13;
function makeOffset(dir) {
  var offset = 20,
      base = dir ? 0 : (0 - offset);
  $($('.active').get().reverse()).each(function() {
    $(this).css('transform','translateX(' + base + 'px)');
    base = base - offset;
  })
}

$('.item').on('click',function() {
  var $target = $('#'+$(this).attr('data-target-id'));
  makeOffset();
  $target.toggleClass('active');
});

$('.back').on('click',function() {
  $(this).closest('.rmenu').removeClass('active').css('transform','');
  makeOffset('back');
})
&#13;
body {
  background-color: darkgray;
  overflow: hidden;
}
#menu {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 300px;
}
.rmenu {
  position: absolute;
  right: 0;
  transform: translateX(100%);
  bottom: 0;
  width: 200px;
  transition: transform .2s;
  border: 1px solid gray;
}
.rmenu.active {
  transform: translateX(0);
}
.rmenu div {
  background-color: white;
  border-bottom: 1px solid gray;
}
.rmenu div:last-child {
  border: none;
}
.rmenu .title {
  text-align: center;
  padding: 5px;
  color: gray;
}
.rmenu .item {
  padding: 3px;
  cursor: pointer;
}
.rmenu .back {
  padding-right: 5px;
  cursor: pointer;
}
.rmenu .submenu-indicator {
  float: right;
  padding-right: 5px;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="menu">
  <!--main menu-->
  <div id="home" class="rmenu active">
    <div class="title">
      <span>Home</span>
    </div>
    <div data-target-id="items" data-target-type="menu" class="item">
      <span class="label">Items</span><span class="submenu-indicator">></span>
    </div>
    <div class="item">
      <span class="label">Social</span>
    </div>
    <div class="item">
      <span class="label">Settings</span>
    </div>
  </div>

  <!--items menu-->
  <div id="items" class="rmenu" data-parent-id="home">
    <div class="title">
      <span class="back">&lt;</span><span>Items</span>
    </div>
    <div class="item" data-target-id="tables" data-target-type="menu">
      <span class="label">Tables</span><span class="submenu-indicator">></span>
    </div>
    <div class="item">
      <span class="label">Lamps</span>
    </div>
    <div class="item">
      <span class="label">Chairs</span>
    </div>
  </div>

  <!--tables menu-->
  <div id="tables" class="rmenu" data-parent-id="items">
    <div class="title">
      <span class="back">&lt;</span><span>Tables</span>
    </div>
    <div class="item">
      <span class="label">1</span>
    </div>
    <div class="item">
      <span class="label">2</span>
    </div>
    <div class="item">
      <span class="label">3</span>
    </div>
    <div class="item">
      <span class="label">4</span>
    </div>
    <div class="item">
      <span class="label">5</span>
    </div>
    <div class="item">
      <span class="label">6</span>
    </div>
  </div>
</div>
&#13;
&#13;
&#13;