我想要实现的是在元素数组上排队一些动画(使用 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“默认”样式,将 .btn
从 btn-something
更改为 时就会遇到问题btn-somethingElse
。因为 Twitter Bootstrap 使用 background-color
之上的 background-image
属性来创建这些渐变阴影。而且background-image
并不完全可动画化。
所以你有两个选择:
- 您必须删除
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>
克隆有点复杂,因为您需要保留现有的 id
、style
、data
和 events
原始元素并将它们传递给克隆,确保克隆函数不会修改任何内容。此外,通过克隆,您需要从克隆函数返回克隆,因为它会删除原始元素,因此任何后续动画最终都将没有主题。
交错的简单方法是使用 $.each()
,因为它在内部创建所需的闭包。如果您想要/必须在普通版本中执行此操作,则必须使用经典的 for()
并将 setTimeout()
包装在将当前时间传递给的闭包中元素,否则 this
会变成 err!?
并且交错动画消失。
关于设计模式:
一般来说,在对集合进行动画处理时,如果间隔/步长是恒定的,则将下一个动画的开始绑定(bind)到前一个动画的结束被认为是不好的做法和主要限制,因为步长必须长于期间。仅当效果的持续时间可能显着变化时才执行此操作,并且通常使用循环延迟/ promise 构造来执行此操作。
但通常您应该将步长(间隔)和效果持续时间保存在两个单独的变量中。请参阅我对 a similar question 的回答了解详情。
关于javascript - 如何在元素数组上链接 jQuery addClass() 和 removeClass(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44101402/