老师,针对之前的遗留问题(js和发送消息),客服老师已经发给我了,但是看不太懂
还想请老师帮我解释一下修改的思路
我的问题的链接:(js动画失效问题和发送消息问题)(第二种滑入滑出方试)
https://class.imooc.com/course/qadetail/193450
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | ( 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上
可以看一下下面的注释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | 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事件中传入参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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积分~
来为老师/同学的回答评分吧