老师,针对之前的遗留问题(js和发送消息),客服老师已经发给我了,但是看不太懂

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


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

3回答
好帮手慕慕子 2020-04-10 20:11:15

同学你好,对于你的问题解答如下:

  1. 理解是对的。

  2. 参数是用来计算索引的,不传的话就是undefined,计算结果为NAN,不会报错的。只要执行了trigger事件,就会发送消息,触发事件,只是前面显示的索引是NAN而已。可以换成css方式,测试下,如下:

    http://img1.sycdn.imooc.com//climg/5e90622f095f354506400410.jpg

同学可以试着理解下,如果还有疑惑,可以详细描述下具体是哪里不明白,我们会继续为您解答的,祝学习愉快~

好帮手慕慕子 2020-04-10 11:45:08

同学你好,对于你的问题解答如下:

  1. 可以查看下move.js中css方式是直接通过css方法设置left和top值实现位移,是瞬间移动到指定位置的,而js方式是使用animate方法实现位移,在移动到指定位置时会有一个过渡效果。如下:

    http://img1.sycdn.imooc.com//climg/5e8fe7c40942978a15361270.jpg

  2. js和css方式,slider.js中发送消息是相同的,两者不同的是move.js中css和js的位移方式(也就是to方法)。

同学可以试着理解下,祝学习愉快~

  • 提问者 迷失的小麦 #1
    关于问题2,可能我的意思没表达清楚。js和css方式,既然发送消息是相同的,那么触发moved事件的时候,只有js传入了参数originalLeft,而css并没有在move.js中传入参数originalLeft,为什么这样写代码还没报错? (当使用css时slider-hidden的事件)
    2020-04-10 12:24:57
  • 提问者 迷失的小麦 #2
    关于问题1,我能否这样理解: css是没有移动过程的,只是肉眼上有个动画效果。而js是有一个移动过程,所以肉眼上有个动画效果。(但是感觉这样理解很牵强)
    2020-04-10 12:26:47
  • 提问者 迷失的小麦 #3
    打漏了,问题2是slider-hidden和slider-shown
    2020-04-10 12:28:07
好帮手慕星星 2020-04-09 17:26:19

同学你好,问题解答如下:

1、js方式移动的问题

当索引为0的时候,会进行两次移动

http://img1.sycdn.imooc.com//climg/5e8ee813091bdeb115980579.jpg

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

http://img1.sycdn.imooc.com//climg/5e8ee3f709b882d316780705.jpg

http://img1.sycdn.imooc.com//climg/5e8ee8510944150e14940635.jpg最外层的if相对应的else也可以添加判断

http://img1.sycdn.imooc.com//climg/5e8ee8ac09aa2f8c12160263.jpg

2、发送消息这部分比较复杂,修改的地方较多

(1)代码中调用move方法是this.$container元素

http://img1.sycdn.imooc.com//climg/5e8ee982097409a707240088.jpg

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

http://img1.sycdn.imooc.com//climg/5e8ee9c009705df506970113.jpg

可以看一下下面的注释

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
    老师说是js方式移动的问题的原因是当索引为0的时候,会进行两次移动,那为什么当css方式移动时不会出现错误,我对这里的原理有点晕,不太理解
    2020-04-09 20:21:18
  • 提问者 迷失的小麦 #2
    另外,关于发送消息,为什么originalLeft写在了js里面,如果是css呢?
    2020-04-10 11:07:17
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
2.组件化网页开发
  • 参与学习           人
  • 提交作业       1121    份
  • 解答问题       14456    个

本阶段在运用JS实现动态网页开发的基础上,带你深入理解企业开发核心思想,完成一个企业级网页的开发,体验前端工程师的成就感。

了解课程
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师
插入代码