老师,针对之前的遗留问题(js和发送消息),客服老师已经发给我了,但是看不太懂
还想请老师帮我解释一下修改的思路
我的问题的链接:(js动画失效问题和发送消息问题)(第二种滑入滑出方试)
https://class.imooc.com/course/qadetail/193450
(function($) {
'use strict';
function Slider($elem, options) {
this.$elem = $elem;
this.options = options;
this.$items = this.$elem.find('.slider-item');
this.$indicators = this.$elem.find('.slider-indicator');
// this.$controlLeft=this.$elem.find('.slider-control-left');
// this.$controlRight=this.$elem.find('.slider-control-right');
this.$controls = this.$elem.find('.slider-control');
this.itemNum = this.$items.length;
this.curIndex = this._getCorrectIndex(this.options.activeIndex);
this._init();
}
Slider.DEFAULTS = {
css3: false,
js: false,
animation: 'fade', // slide
activeIndex: 0,
interval: 0,
loop: false
};
Slider.prototype._init = function() {
var self = this;
// init show
this.$indicators.removeClass('slider-indicator-active');
this.$indicators.eq(this.curIndex).addClass('slider-indicator-active');
//to
if (this.options.animation === 'slide') {
this.$elem.addClass('slider-slide');
// // this.$items.eq(this.curIndex).css('left', 0);
// 应该用 this.$container 监听事件,而不是 this.$items
// 因为此时移动的是 this.$container
// 所以这里的代码需要往后移,因为此时 this.$container 还没定义
//send message
// this.$items.on('move moved', function(e) {
// var index = self.$items.index(this);
// if (e.type === 'move') {
// if (index === self.curIndex) {
// self.$elem.trigger('slider-hide', [index, this]);
// } else {
// self.$elem.trigger('slider-show', [index, this]);
// }
// } else {
// // moved
// if (index === self.curIndex) {
// // 指定的
// self.$elem.trigger('slider-shown', [index, this]);
// } else {
// self.$elem.trigger('slider-hidden', [index, this]);
// }
// }
// });
// // move init
// this.$items.move(this.options);
this.to = this._slide;
this.$container = this.$elem.find('.slider-container');
this.itemWidth = this.$items.eq(0).width();
this.$container.css('left', -1 * this.curIndex * this.itemWidth);
// this.itemWidth = this.$items.eq(0).width();
// this.transitionClass = this.$items.eq(0).hasClass('transition') ? 'transition' : '';
// 移到这里来
// 多接收了两个参数:$container 表示正在移动的元素;distLeft 表示移动完成后,移动元素 的 left值
// 这里需要修改 move.js 的 to 方法,在触发move事件时,多传递2个参数
// 也需要修改 move.js 的 Js.prototype.to 方法,在触发 moved 事件时,多传递4个参数
this.$container.on('move moved', function(
e,
$container,
distLeft,
distTop,
originalLeft,
originalTop
) {
// 计算 index 的方法错了,此时移动的是 this.$container
// 这样是无法计算它的索引的,总是 -1
// var index = self.$items.index(this);
if (e.type === 'move') {
// 想要计算移动前的索引是多少
var left = parseInt($container.css('left'));
// 计算出移动刚开始时的索引值
var index = Math.abs(parseInt(left / self.itemWidth));
// 计算出移动完成后的索引值
var distIndex = Math.abs(parseInt(distLeft / self.itemWidth));
// console.log(index, self.curIndex);
// console.log(index, distIndex);
// 当前的开始隐藏
self.$elem.trigger('slider-hide', [index, this]);
// 移动完成后的开始显示
self.$elem.trigger('slider-show', [distIndex, this]);
// if (index === self.curIndex) {
// self.$elem.trigger('slider-hide', [index, this]);
// } else {
// self.$elem.trigger('slider-show', [index, this]);
// }
} else {
// moved
// 计算出移动刚开始时的索引值
var index = Math.abs(parseInt(originalLeft / self.itemWidth));
// 计算出移动完成后的索引值
var distIndex = Math.abs(parseInt(distLeft / self.itemWidth));
// 移动刚开始时的那个幻灯片完全隐藏
self.$elem.trigger('slider-hidden', [index, this]);
// 移动完成后的那个幻灯片完全显示
self.$elem.trigger('slider-shown', [distIndex, this]);
// if (index === self.curIndex) {
// // 指定的
// self.$elem.trigger('slider-shown', [index, this]);
// } else {
// self.$elem.trigger('slider-hidden', [index, this]);
// }
}
});
//move init
this.$container.move(this.options);
if (this.options.loop) {
this.$container.append(this.$items.eq(0).clone());
this.transitionClass = this.$container.hasClass('transition')
? 'transition'
: '';
this.itemNum++;
}
} else {
this.$elem.addClass('slider-fade');
this.$items.eq(this.curIndex).show();
// send message
this.$items.on('show shown hide hidden', function(e) {
self.$elem.trigger('slider-' + e.type, [self.$items.index(this), this]);
// 发送消息,同时传参当前显示的第几个及该DOM
});
// showHide init
this.$items.showHide(this.options);
this.to = this._fade;
}
//bind event
this.$elem
.hover(
function() {
self.$controls.show();
},
function() {
self.$controls.hide();
}
)
.on('click', '.slider-control-left', function() {
self.to(self._getCorrectIndex(self.curIndex - 1), 1); //通过第二个参数有无来确定是点击的箭头还是下面的圆点
})
.on('click', '.slider-control-right', function() {
self.to(self._getCorrectIndex(self.curIndex + 1), -1);
})
.on('click', '.slider-indicator', function() {
self.to(self._getCorrectIndex(self.$indicators.index(this)));
});
// auto
if (this.options.interval && !isNaN(Number(this.options.interval))) {
this.$elem.hover($.proxy(this.pause, this), $.proxy(this.auto, this));
this.auto();
}
};
Slider.prototype._getCorrectIndex = function(index, maxNum) {
maxNum = maxNum || this.itemNum;
if (isNaN(Number(index))) return 0;
if (index < 0) return maxNum - 1;
if (index > maxNum - 1) return 0;
return index;
};
Slider.prototype._activateIndicators = function(index) {
// this.$indicators.eq(this.curIndex).removeClass('slider-indicator-active');
this.$indicators.removeClass('slider-indicator-active');
this.$indicators.eq(index).addClass('slider-indicator-active');
};
Slider.prototype._fade = function(index) {
if (this.curIndex === index) return;
this.$items.eq(this.curIndex).showHide('hide');
this.$items.eq(index).showHide('show');
this._activateIndicators(index);
this.curIndex = index;
};
Slider.prototype._slide = function(index, direction) {
if (this.curIndex === index) return;
var self = this;
// 之前有停顿问题的原因就在于这里
// 因为这里一上来就开始运动了,后面判断完该往哪里运动后,又开启了一次运动,相当于有2次运动,造成了冲突
// 所以把这里的运动注释掉,放在后面的 if 分支中,保证同一时间只有一次运动
// this.$container.move('x', -1 * index * this.itemWidth);
// this.curIndex = index;
if (this.options.loop && direction) {
if (direction < 0) {
if (index === 0) {
console.log(index);
this.$container.removeClass(this.transitionClass).css('left', 0);
this.curIndex = index = 1;
setTimeout(function() {
self.$container
.css('left', 0)
.addClass(self.transitionClass)
.move('x', -1 * index * self.itemWidth);
}, 20);
} else {
// 这里是新增的分支,表示当 direction < 0 时,index !=0 的情况下该怎么运动
// 其实就是把上面注释掉的代码,拿过来了
this.$container.move('x', -1 * index * this.itemWidth);
this.curIndex = index;
}
} else {
if (index === this.itemNum - 1) {
console.log(index);
this.$container
.removeClass(this.transitionClass)
.css('left', -1 * index * this.itemWidth);
this.curIndex = index = this.itemNum - 2;
setTimeout(function() {
self.$container
.addClass(self.transitionClass)
.css('left', -1 * (self.itemNum - 1) * self.itemWidth)
.move('x', -1 * index * self.itemWidth);
}, 20);
} else {
// 这里是新增的分支,表示当 direction >= 0 时,index != this.itemNum - 1 的情况下该怎么运动
// 其实就是把上面注释掉的代码,拿过来了
this.$container.move('x', -1 * index * this.itemWidth);
this.curIndex = index;
}
}
index = this._getCorrectIndex(index, this.itemNum - 1);
} else {
// 这里是新增的分支,表示当 this.options.loop!=true或direction没有值的情况下该怎么运动
// 其实就是把上面注释掉的代码,拿过来了
this.$container.move('x', -1 * index * this.itemWidth);
this.curIndex = index;
}
this._activateIndicators(index);
// if (this.curIndex === index) return;
// var self = this;
// // 确定滑入滑出的方向
// if (!direction) { // click indicators
// if (this.curIndex < index) {
// direction = -1;
// } else if (this.curIndex > index) {
// direction = 1;
// }
// }
// // 设置指定滑入幻灯片的初始位置
// this.$items.eq(index).removeClass(this.transitionClass).css('left', -1 * direction * this.itemWidth);
// // 当前幻灯片滑出可视区域,指定幻灯片滑入可视区域
// setTimeout(function() {
// self.$items.eq(self.curIndex).move('x', direction * self.itemWidth);
// self.$items.eq(index).addClass(self.transitionClass).move('x', 0);
// self.curIndex = index;
// }, 20);
// // 激活indicator
// this._activateIndicators(index);
};
Slider.prototype.auto = function() {
var self = this;
this.intervalId = setInterval(function() {
self.to(self._getCorrectIndex(self.curIndex + 1), -1);
}, this.options.interval);
};
Slider.prototype.pause = function() {
clearInterval(this.intervalId);
};
$.fn.extend({
slider: function(option) {
return this.each(function() {
var $this = $(this),
slider = $this.data('slider'),
options = $.extend(
{},
Slider.DEFAULTS,
$(this).data(),
typeof option === 'object' && option
);
// dropdown(this, options);
if (!slider) {
//解决多次调用dropdown问题
$this.data('slider', (slider = new Slider($this, options)));
}
if (typeof slider[option] === 'function') {
slider[option]();
}
});
}
});
})(jQuery);43
收起
正在回答 回答被采纳积分+1
3回答
好帮手慕星星
2020-04-09 17:26:19
同学你好,问题解答如下:
1、js方式移动的问题
当索引为0的时候,会进行两次移动

运动都是需要时间的,两次叠加在一起,效果上就会有问题。所以需要将一开始的移动的代码注释掉,分别在不同方向上添加else判断,如下

最外层的if相对应的else也可以添加判断

2、发送消息这部分比较复杂,修改的地方较多
(1)代码中调用move方法是this.$container元素

所以on绑定事件也需要在这个元素上,而不是$items上

可以看一下下面的注释
Slider.prototype._init = function() {
var self = this;
this.$indicators.removeClass('slider-indicator-active');
this.$indicators.eq(this.curIndex).addClass('slider-indicator-active');
if (this.options.animation === 'slide') {
this.$elem.addClass('slider-slide');
// 这里不应该监听 this.$items 上的事件,而应该监听 this.$container 上的事件
// 因为此时移动的是 this.$container,而不是 this.$items
// 这里的代码需要往后移,因为此时 this.$container 还没定义
// 需要移动到 this.$container 定义后,再来监听相关事件
// 所以这里先注释掉
//send message
// this.$items.on('move moved', function(e) {
// var index = self.$items.index(this);
// if (e.type === 'move') {
// if (index === self.curIndex) {
// self.$elem.trigger('slider-hide', [index, this]);
// } else {
// self.$elem.trigger('slider-show', [index, this]);
// }
// } else {
// // moved
// if (index === self.curIndex) {
// // 指定的
// self.$elem.trigger('slider-shown', [index, this]);
// } else {
// self.$elem.trigger('slider-hidden', [index, this]);
// }
// }
// });
this.to = this._slide;
this.$container = this.$elem.find('.slider-container');
this.itemWidth = this.$items.eq(0).width();
this.$container.css('left', -1 * this.curIndex * this.itemWidth);
// 上面注释掉的代码移到这里来了
// 监听 this.$container 上的事件
// 我们的目标是将 move 和 moved 这两个事件,转换成 slider-show、slider-hide、slider-shown 和 slider-hidden 四个事件
// 在监听到 move 事件时,表示幻灯片开始运动了,我们需要将其转换成 slider-show 和 slider-hide
// 此时我们需要根据 this.$container 的偏移位置,计算出当前显示的是第几张幻灯片(就是索引值是多少),这张幻灯片就是开始隐藏的幻灯片(slider-hide)
// 再根据传入的 distLeft 参数(this.$container 运动到目的地后的偏移位置,因为我们这里改变的是 left 值,所以起名叫 distLeft),计算出将要显示的是第几张幻灯片,这张幻灯片就是开始显示的幻灯片(slider-show)
// 在监听到 moved 事件时,表示幻灯片已经运动完成了,我们需要将其转换成 slider-shown 和 slider-hidden
// 此时我们需要根据 this.$container 的当前位置,计算出当前显示的是第几张幻灯片,这张幻灯片就是已经完全显示了的幻灯片(slider-shown)
// 再根据传入的 originalLeft 参数(this.$container 刚开始运动时的偏移位置),计算出这是第几张幻灯片,这张幻灯片就是已经完全隐藏了的幻灯片(slider-hidden)
// 这里需要多接收两个参数 distLeft 和 originalLeft,帮助我们计算幻灯片的索引值
// distLeft 参数是由 move.js 的 to 方法在触发 move 事件时传递的,需要在 move.js 的 to 方法中添加这一步
// originalLeft 参数是由 move.js 的 Js.prototype.to 方法在触发 moved 事件时传递的,需要在 move.js 的 Js.prototype.to 方法中添加这一步
this.$container.on('move moved', function(
e,
$container,
distLeft,
originalLeft
) {
if (e.type === 'move') {
// 计算刚开始运动时,将要隐藏的幻灯片的索引值
var left = parseInt($container.css('left'));
var index = Math.abs(parseInt(left / self.itemWidth));
// 计算运动到目的地后,将要显示的幻灯片的索引值
var distIndex = Math.abs(parseInt(distLeft / self.itemWidth));
// 刚开始运动时,将要隐藏的幻灯片开始隐藏
self.$elem.trigger('slider-hide', [index, this]);
// 运动到目的地后,将要显示的幻灯片开始显示
self.$elem.trigger('slider-show', [distIndex, this]);
} else {
// moved
// 计算出已经完全隐藏了的幻灯片的索引值
var index = Math.abs(parseInt(originalLeft / self.itemWidth));
// 计算出已经完全显示了的幻灯片的索引值
var distIndex = Math.abs(parseInt(distLeft / self.itemWidth));
// 触发事件,表示幻灯片已经完全隐藏
self.$elem.trigger('slider-hidden', [index, this]);
// 触发事件,表示幻灯片已经完全显示
self.$elem.trigger('slider-shown', [distIndex, this]);
}
});
this.$container.move(this.options);
if (this.options.loop) {
this.$container.append(this.$items.eq(0).clone());
this.transitionClass = this.$container.hasClass('transition') ?
'transition' :
'';
this.itemNum++;
}
} else {
this.$elem.addClass('slider-fade');
this.$items.eq(this.curIndex).show();
this.$items.on('show shown hide hidden', function(e) {
self.$elem.trigger('slider-' + e.type, [self.$items.index(this), this]);
});
this.$items.showHide(this.options);
this.to = this._fade;
}
this.$elem
.hover(
function() {
self.$controls.show();
},
function() {
self.$controls.hide();
}
)
.on('click', '.slider-control-left', function() {
self.to(self._getCorrectIndex(self.curIndex - 1), 1);
})
.on('click', '.slider-control-right', function() {
self.to(self._getCorrectIndex(self.curIndex + 1), -1);
})
.on('click', '.slider-indicator', function() {
self.to(self._getCorrectIndex(self.$indicators.index(this)));
});
if (this.options.interval && !isNaN(Number(this.options.interval))) {
this.$elem.hover($.proxy(this.pause, this), $.proxy(this.auto, this));
this.auto();
}
};move.js中也需要修改,在触发move和move.js事件中传入参数
var to = function (x, y, callback) {
x = typeof x === 'number' ? x : this.curX;
y = typeof y === 'number' ? y : this.curY;
if (this.curX === x && this.curY === y) return;
// 这里需要把想要移动到哪里传递出去(也就是 distLeft 参数)
// this.$elem.trigger('move', [this.$elem]);
this.$elem.trigger('move', [this.$elem, x]);
if (typeof callback === 'function') {
callback();
}
this.curX = x;
this.curY = y;
};Js.prototype.to = function (x, y) {
var self = this;
// 需要修改这里,计算出运动元素的初始 left 值(也就是 originalLeft)
var originalLeft = parseInt(self.$elem.css('left'));
to.call(this, x, y, function () {
self.$elem.stop().animate(
{
left: x,
top: y
},
function () {
// 在触发 moved 事件时,多传递 2 个参数
// self.$elem.trigger('moved', [self.$elem]);
self.$elem.trigger('moved', [self.$elem, x, originalLeft]);
}
);
});
};自己再理解下,祝学习愉快!


恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星