使用JSX实现Carousel轮播组件的方法(前端组件化)(6)

this.root.addEventListener('mousedown', event => { console.log('mousedown'); let move = event => { console.log('mousemove'); }; let up = event => { this.root.removeEventListener('mousemove', move); this.root.removeEventListener('mouseup', up); }; this.root.addEventListener('mousemove', move); this.root.addEventListener('mouseup', up); });

这里我们在 mouseup 的时候就把 mousemove 和 mouseup 的事件给移除了。这个就是一般我们在做拖拽的时候都会用到的基础代码。

但是我们又会发现另外一个问题,鼠标点击拖动然后松开后,我们鼠标再次在图片上移动,还是会出发到我们的mousemove 事件。

这个是因为我们的 mousemove 是在 root 上被监听的。其实我们的 mousedown 已经是在 root 上监听,我们 mousemove 和 mouseup 就没有必要在 root 上监听了。

所以我们可以在 document 上直接监听这两个事件,而在现代浏览器当中,使用 document 监听还有额外的好处,即使我们的鼠标移出浏览器窗口外我们一样可以监听到事件。

this.root.addEventListener('mousedown', event => { console.log('mousedown'); let move = event => { console.log('mousemove'); }; let up = event => { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', up); }; document.addEventListener('mousemove', move); document.addEventListener('mouseup', up); });

有了这个完整的监听机制之后,我们就可以尝试在 mousemove 里面去实现轮播图的移动功能了。我们一起来整理一下这个功能的逻辑:

要做这个功能,首先我们要知道鼠标的位置,这里可以使用 mousemove 中的 event 参数去捕获到鼠标的坐标。event 上其实有很多个鼠标的坐标,比如 offsetX、offsetY 等等,这些都是根据不同的参考系所获得坐标的。在这里我们比较推荐使用的是 clientX 和 clientY这个坐标是相对于整个浏览器中可渲染区域的坐标,它不受任何的因素影响。很多时候我们组件在浏览器这个容器里面,当我们滚动了页面之后,在一些坐标体系中就会发生变化。这样我们就很容易会出现一些不可调和的 bug,但是 clientX 和 clientY 就不会出现这种问题。如果要知道我们图片要往某一个方向移动多少,我们就要知道我们鼠标点击时的起始坐标,然后与我们获取到的 clientX 和 clientY 做对比。所以我们需要记录一个 startX 和 startY,它们的默认值就是对应的当前 clientX 和 clientY所以我们鼠标移动的距离就是 终 点 坐 标 − 起 点 坐 标 终点坐标 - 起点坐标 终点坐标−起点坐标,在我们的 move 回调函数里面就是 clientX - startX 和 clientY - startY我们轮播图只支持左右滑动的,所以在我们这个场景中,就不需要 Y 轴的值。那么我们计算好移动距离,就可以给对应被拖动的元素加上 transform,这样图片就会被移动了我们之前做自动轮播的时候给图片元素加入了 transition 动画,我们在拖动的时候如果有这个动画,就会出现延迟一样的效果,所以在给图片加入 transform 的同时,我们还需要禁用它们的 transition 属性

this.root.addEventListener('mousedown', event => { let children = this.root.children; let startX = event.clientX; let move = event => { let x = event.clientX - startX; for (let child of children) { child.style.transition = 'none'; child.style.transform = `translateX(${x}px)`; } }; let up = event => { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', up); }; document.addEventListener('mousemove', move); document.addEventListener('mouseup', up); });

好,到了这里我们发现了两个问题:

我们第一次点击然后拖动的时候图片的起始位置是对的,但是我们再点击的时候图片的位置就不对了。我们拖动了图片之后,当我们松开鼠标按钮,这个图片就会停留在拖动结束的位置了,但是在正常的轮播图组件中,我们如果拖动了图片超过一定的位置,就会自动轮播到下一张图的。

要解决这两个问题,我们可以这么计算,因为我们做的是一个轮播图的组件,按照现在一般的轮播组件来说,当我们把图片拖动在大于半个图的位置时,就会轮播到下一张图了,如果不到一半的位置的话就会回到当前拖动的图的位置。

按照这样的一个需求,我们就需要记录一个 position,它记录了当前是第几个图片(从 0 开始计算)。如果我们每张图片都是 500px 宽,那么第一张图的 current 就是 0,偏移的距离就是 0 * 500 = 0, 而第二张图就是 1 * 500 px,第三张图就是 2 * 500px,以此类推。根据这样的规律,第 N 张图的偏移位置就是 n ∗ 500 n * 500 n∗500。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsdgsj.html