我正在制作一个包含游戏列表的页面。我添加了按类型过滤游戏的单选按钮。当用户点击类型过滤器时,我正在使用jQuery优雅地淡入淡出游戏列表。
问题在于,每次单击单选按钮时,游戏列表都会笨拙地淡入和淡出两次。请参阅:http://jsfiddle.net/animeguy99/pZKda/1/
以下是我使用的脚本:
$('input[name$="group1"]').click(function(){
var radio_value = $(this).val();
if(radio_value=='Adventure') {
$('#games div').fadeOut('slow', function(){
$('#games .adv').fadeIn();
});
}
else if(radio_value=='Puzzle') {
$('#games div').fadeOut('slow', function(){
$('#games .puz').fadeIn();
});
}
else if(radio_value=='Shooter') {
$('#games div').fadeOut('slow', function(){
$('#games .sho').fadeIn();
});
}
else if(radio_value=='All') {
$('#games div').fadeOut('slow', function(){
$('#games div').fadeIn();
});
}
});
我有DIV类声明的类型类型。因此,每次用户点击收音机时,我都会淡出所有DIV(游戏),然后通过DIV课程淡出所请求的流派。
当我用Google搜索时,类似的案例表明这可能是父/子问题。但我对如何将其与我的剧本联系起来感到困惑。
我在俯瞰什么?
答案 0 :(得分:1)
.fadeOut()
和.fadeIn()
的回调函数无法按照多个元素褪色时的预期方式运行。回调不只调用一次,而是调用每个元素。
如果您在其中一个console.log()
回调中发出.fadeOut()
来电,您会看到它被多次记录。 (Chrome开发人员工具会将其折叠为单个日志条目,左侧有一个数字。)
回调函数
如果提供,则动画完成后将触发回调。这对于按顺序将不同的动画串联在一起非常有用。回调不会发送任何参数,但这被设置为动画的DOM元素。如果动画了多个元素,请务必注意每个匹配元素执行一次回调,而不是整个动画执行一次。
从jQuery 1.6开始,.promise()方法可以与deferred.done()方法结合使用,在所有匹配元素完成动画时,为整个动画执行单个回调(参见示例for .promise())。
以下是使用.promise()
删除重复回调的代码版本。它还包含了j08691的建议,即从fadeOut中排除你将要消失的元素:
var groups = {
Adventure: '.adv',
Puzzle: '.puz',
Shooter: '.sho',
All: 'div'
};
function fade( group ) {
$('#games div')
.not(group)
.fadeOut()
.promise()
.done( function() {
console.log( group );
$('#games ' + group).fadeIn();
});
}
$('input[name$="group1"]').click(function () {
fade( groups[ $(this).val() ] );
});
通过将重复代码组合到单个函数中,此代码也比原始代码大大简化。最后,我离开了console.log()来查看正在进行的调用。
还有一些关于HTML的评论:除非你正在编写XHTML,否则你不需要使用<br />
,我希望你没有这样做。 <br>
没问题。更重要的是,您应该在单选按钮标签上使用<label>
标签,以便整个标签可以点击:
<label><input type="radio" name="group1" value="All" checked>Show All</label><br>
<label><input type="radio" name="group1" value="Adventure">Adventure</label><br>
<label><input type="radio" name="group1" value="Puzzle">Puzzle</label><br>
<label><input type="radio" name="group1" value="Shooter">Shooter</label>
这是一个updated jsfiddle。
此处还有其他简化机会。是否要求单选按钮中的value
属性为特定字符串'All','Adventure'等?如果没有,您可以直接将组选择器放在value
属性中:
<label><input type="radio" name="group1" value="div" checked>Show All</label><br>
<label><input type="radio" name="group1" value=".adv">Adventure</label><br>
<label><input type="radio" name="group1" value=".puz">Puzzle</label><br>
<label><input type="radio" name="group1" value=".sho">Shooter</label>
然后将JavaScript代码简化为:
function fade( group ) {
$('#games div')
.not(group)
.fadeOut()
.promise()
.done( function() {
console.log( group );
$('#games ' + group).fadeIn();
});
}
$('input[name$="group1"]').click(function () {
fade( $(this).val() );
});
另一个更新......正如Alex在评论中指出的那样,当您在Show All和特定类型之间来回点击时,此版本的代码会导致块跳转。
这是由代码中的这一行引起的:
.not(group)
删除该行可以提供更平滑的过渡,如updated jsfiddle所示。
答案 1 :(得分:1)
试试这个小提琴。
问题出在您的jQuery Selector $('#games div')
上。您的选择指向多个DOM元素。因此,它将为范围中的每个元素运行fadeOut()
,然后对每个运行fadeIn()
的元素运行回调。添加额外的选择器将确保它只运行一次。
$('#games div').filter(":visible")
添加.filter(":visible")
限制将确保只有那些可见的应该被淡出(如果不使用过滤器,那么如果隐藏选择的任何元素,它将立即触发fadeIn()
) 。此外,它还将确保fadeIn()
仅在选择中可见的所有元素现在都隐藏后才会运行。
答案 2 :(得分:0)
你需要首先淡出元素组(通过类似.not('.puz')
之类的东西),否则jQuery会首先使它们再次可见,然后淡出它们。试试这个(为了清晰起见,添加了延迟):
$('input[name$="group1"]').click(function () {
var radio_value = $(this).val();
if (radio_value == 'Adventure') {
$('#games div').not('.adv').fadeOut(3000,function () {
$('#games .adv').fadeIn(3000);
});
} else if (radio_value == 'Puzzle') {
$('#games div').not('.puz').fadeOut(3000,function () {
$('#games .puz').fadeIn(3000);
});
} else if (radio_value == 'Shooter') {
$('#games div').not('.sho').fadeOut(3000,function () {
$('#games .sho').fadeIn(3000);
});
} else if (radio_value == 'All') {
$('#games div').fadeOut(3000, function () {
$('#games div').fadeIn(3000);
});
}
});
<强> jsFiddle example 强>
答案 3 :(得分:0)
问题是当你在几个元素上调用fadeOut时,会多次调用它。并且触发fadeIn的回调被调用相同的次数。你不需要那个。只有在完成所有fadeOuts时才需要开始调用fadeIn。
其中一种方法是使用$ .when .. $ done sequence:
$.when(
$('#games div').fadeOut('slow');
).done(function() {
$('#games .adv').fadeIn();
});
http://api.jquery.com/jQuery.when/
http://api.jquery.com/deferred.done/
答案 4 :(得分:0)
如果使用html5数据类型属性,则操作简单。结帐jsfiddle
。