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

首先当我们 mousemove 的时候,我们需要计算当前图片已经从起点移动了多远,这个就可以通过 N * 500 来计算,这里的 N 就是目前的图片的 position 值。然后我们还需要在 mouseup 的时候,计算一下当前图片移动的距离是否有超过半张图的长度,如果超过了,我们直接 transform 到下一张图的起点位置这里的超出判断可以使用我们当前鼠标移动的距离 x 除与我们每张图的 长度(我们这个组件控制了图片是 500px,所以我们就用 x 除与 500),这样我们就会得出一个 0 到 1 的数字。如果这个数字等于或超过 0.5 那么就是过了图一半的长度了,就可以直接轮播到下一张图,如果是小于 0.5 就可以移动回去当前图的起始位置。上面计算出来的值,还可以结合我们的 position,如果大于等于 0.5 就可以四舍五入变成 1, 否则就是 0。这里的 1 代表我们可以把 position + 1,如果是 0 那么 position 就不会变。这样直接改变 current 的值,在 transform 的时候就会自动按照新的 current 值做计算,轮播的效果就达成了。因为 x 是可以左右移动的距离值,也就是说如果我们鼠标是往左移动的话,x 就会是负数,而相反就是正数,我们的轮播组件鼠标往左拖动就是前进,而往右拖动就是回退。所以这里运算这个 超出值 的时候就是 position = position - Math.round(x/500) 。比如我们鼠标往左边挪动了 400px,当前 current 值是 0,那么position = 0 - Math.round(400/500) = 0 - -1 = 0 + 1 = 1 所以最后我们的 current 变成了 1。根据上面的逻辑,我们在 mouseup 的事件中要循环所有轮播中的 child 图片,给它们都设置一个新的 tranform 值

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 - current * 500}px)`; } }; let up = event => { let x = event.clientX - startX; current = current - Math.round(x / 500); for (let child of children) { child.style.transition = ''; child.style.transform = `translateX(${-current * 500}px)`; } document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', up); }; document.addEventListener('mousemove', move); document.addEventListener('mouseup', up); });

注意这里我们用的 500 作为图片的长度,那是因为我们自己写的图片组件,它的图片被我们固定为 500px 宽,而如果我们需要做一个通用的轮播组件的话,最好就是获取元素的实际宽度,Element.clientWith()。这样我们的组件是可以随着使用者去改变的。

做到这里,我们就可以用拖拽来轮播我们的图片了,但是当我们拖到最后一张图的时候,我们就会发现最后一张图之后就是空白了,第一张图没有接着最后一张。

那么接下来我们就去完善这个功能。这里其实和我们的自动轮播是非常相似的,在做自动轮播的时候我们就知道,每次轮播图片的时候,我们最多就只能看到两张图片,可以看到三张图片的机率是非常小的,因为我们的轮播的宽度相对我们的页面来说是非常小的,除非用户有足够的位置去拖到第二张图以外才会出现这个问题。但是这里我们就不考虑这种因素了。

我们确定每次拖拽的时候只会看到两张图片,所以我们也可以像自动轮播那样去处理拖拽的轮播。但是这里有一个点是不一样的,我们自动轮播的时候,图片只会走一个方向,要么左要么右边。但是我们手动就可以往左或者往右拖动,图片是可以走任意方向的。所以我们就无法直接用自动轮播的代码来实现这个功能了。我们就需要自己重新处理一下轮播头和尾无限循环的逻辑。

我们可以从 mousemove 的回调函数开始改造需要找到当前元素在屏幕上的位置,我们给它 一个变量名叫 current,它的值与我们之前在 mouseup 计算的 position 是一样的 position + Math.round(x/500)但是当前这个元素是前后都有一张图,这里我们就不去计算现在拖动是需要拼接它前面还是后面的图,我们直接就把当前元素前后两个图都移动到对应的位置即可这里我们直接循环一个 [-1, 0, 1] 的数组,对应的是前一个元素,当前元素和下一个元素,这里我们需要使用这三个偏移值,获取到上一个图片,当前拖动的图片和下一个图片的移动位置,这三个位置是跟随着我们鼠标的拖动实时计算的接着我们在这个循环里面需要先计算出前后两张图的位置,图片位置 = 当前图片位置 + 偏移,这里可以这么理解如果当前图片是在 2 这个位置,上一张图就是在 1,下一张图就在 3但是这里有一个问题,如果我们当前图是在 0 的位置,我们上一张图获取到的位置就是 -1,按照我们图片的数据结构来说,数组里面是没有 -1 这个位置的。所以当我们遇到计算出来的位置是负数的时候我们就要把它转成这一列图片的最后一张图的位置。按照我们的例子里面的图片数据来说的话,当前的图是在 0 这个位置,那么上一张图就应该是我们在3 号位的图。那么我们怎么能把 -1 变成 3, 在结尾的时候 4 变成 0 呢?这里需要用到一个数学中的小技巧了,如果我们想让头尾的两个值超出的时候可以翻转,我们就需要用到一个公式, 求 (当前指针 + 数组总长度)/ 数组总长度 的 余数,这个获得的余数就正好是翻转的。

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

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