javascript - 如何在元素数组上链接 jQuery addClass() 和 removeClass()

标签 javascript jquery css animation css-transitions

我想要实现的是在元素数组上排队一些动画(使用 CSS3 转换和 addClass()、removeClass())。我尝试了多种排队机制,但不幸的是它们的行为不符合预期。

正确的结果是将“btn-danger”类添加到按钮,然后在转换结束时删除该类。之后转到下一个元素,依此类推。这是一个动态列表,因此我无法对动画进行硬编码。

这是我的代码的一些示例:

function animateSelections(cb) {
    var randomIndexesArray = [];

    var studentsArray = $('#students-list .btn');
    var studentsArrayLength = studentsArray.length;

    function shuffleArray(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }

    shuffleArray(studentsArray);

    var chain = function(element, index) {
        if (element[index]) {
            $(element[index]).addClass('btn-danger').on('webkitTransitionEnd', function () {
                $(this).removeClass('btn-danger').on('webkitTransitionEnd', function () {
                    chain(element, index + 1);
                });
            });
        }
    };

    chain(studentsArray, 0);

    if (typeof cb != 'undefined') {
        cb();
    }
}
#students-list button {
    font-size: 14px;
    transition: all .3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="students-list">
    <div class="row">            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John 
    Smith </button>
            </div>
            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
</div><div class="row">            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
</div><div class="row">            <div class="col-xs-3">
                <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
            </div>
    </div>

    </div>

代码的当前状态永远不会完成,我认为 transitionend 事件有问题

最佳答案

只要您使用 Bootstrap“默认”样式,将 .btnbtn-something 更改为 时就会遇到问题btn-somethingElse。因为 Twitter Bootstrap 使用 background-color 之上的 background-image 属性来创建这些渐变阴影。而且background-image并不完全可动画化

所以你有两个选择:

  1. 您必须删除 background-image 属性(请参见下面的示例),

示例:

let interval = 300,
    duration = 300;

$('#students-list .btn').each(function(i, e) {
  $(e).css({
    transitionDuration:interval+'ms'
  }).addClass('removeBgImg');
  
  setTimeout(function() {
    $(e).removeClass('btn-primary').addClass('btn-danger');
    setTimeout(function(){
      $(e).removeClass('btn-danger').addClass('btn-primary');
    }, duration + interval)
  }, interval * i);
})
.btn {
  transition-property: background-color;
  transition-timing-function: linear
}
.btn.removeBgImg {
  background-image:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

<div id="students-list" class="container">
  <div class="row">
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John 
    Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
    </div>
    <div class="col-xs-3">
      <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
  </div>
</div>

  • ...或者,如果您不能/不想,只需创建一个绝对位于旧按钮之上的按钮副本,将其淡入,以动画方式不透明度。如果您使用 JavaScript 来执行此操作(这是有道理的),请特别注意使用 ID 克隆元素,因为它们会发出一些极难调试的错误:正确的顺序是:
    • 存储元素 ID,
    • 从元素中删除 ID,
    • 克隆,
    • 为克隆添加 ID,
    • 淡入克隆,
    • 删除原始内容。
  • 示例:

    let interval = 500,
        duration = 100;
    
    $('#students-list .btn').each(function(i, e) {
      setTimeout(function() {
        let clone = fadeCloneIn($(e), 'btn-primary', 'btn-danger');
        setTimeout(function(){
          fadeCloneIn(clone, 'btn-danger', 'btn-primary')
        }, duration + interval)
      }, interval * i);
    })
    
    function fadeCloneIn(el, from, to) {
      let _t = this
      _t.cloner = $('<div />', {style:'position:relative;'});
      _t.id = el.attr('id') ? el.attr('id') : false;
      _t.style = el.attr('style') ? el.attr('style') : false;
      if (_t.id) el.removeAttr('id');
      _t.clone = el.clone(true).removeClass(from).addClass(to).css({
        opacity:0,
        position:'absolute'
      }).appendTo(_t.cloner);
      if (_t.id) _t.clone.attr('id', _t.id);
      _t.cloner.insertBefore(el);
      _t.clone.animate({opacity:1}, interval, function(){
        el.remove();
        $(this).removeAttr('style').unwrap();
        if (_t.style) $(this).attr('style', _t.style);    
      });
      return _t.clone;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    
    <div id="students-list" class="container">
      <div class="row">
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John 
        Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
        </div>
        <div class="col-xs-3">
          <button class="btn btn-block btn-lg btn-primary viable"> John Smith </button>
      </div>
    </div>

    克隆有点复杂,因为您需要保留现有的 idstyledataevents原始元素并将它们传递给克隆,确保克隆函数不会修改任何内容。此外,通过克隆,您需要从克隆函数返回克隆,因为它会删除原始元素,因此任何后续动画最终都将没有主题。


    交错的简单方法是使用 $.each(),因为它在内部创建所需的闭包。如果您想要/必须在普通版本中执行此操作,则必须使用经典的 for() 并将 setTimeout() 包装在将当前时间传递给的闭包中元素,否则 this 会变成 err!? 并且交错动画消失。

    关于设计模式:

    一般来说,在对集合进行动画处理时,如果间隔/步长是恒定的,则将下一个动画的开始绑定(bind)到前一个动画的结束被认为是不好的做法和主要限制,因为步长必须长于期间。仅当效果的持续时间可能显着变化时才执行此操作,并且通常使用循环延迟/ promise 构造来执行此操作。

    但通常您应该将步长(间隔)和效果持续时间保存在两个单独的变量中。请参阅我对 a similar question 的回答了解详情。

    关于javascript - 如何在元素数组上链接 jQuery addClass() 和 removeClass(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44101402/

    相关文章:

    javascript - 单击时 Angular Material md-datepicker 抛出错误

    javascript - 为什么会出现这种情况?

    css - 如何将多个 CSS 文件添加到一个皮肤?

    javascript - 在复选框上显示 map_canvas div

    javascript - 更新 li 元素的属性 data-id Nestable 不更新

    javascript - 如何使用 for Each 在 json 中添加特定值

    jquery - 提交前确认表单

    jquery - 调用双击事件

    javascript数组只显示第一个字符

    html - 框内图像旁边的文本未对齐