老师,针对之前的遗留问题(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 星