一、不要使用offsetX
前几天在公司实习,由于使用了swiper来做c端的滑动效果,在自定义的过程中,出现了一系列的坑,我看了源码,看了文档,也还是没有很好的理解,这个swiper的标准操作流程,当时,就想到能不能自己写一个轮播图上去,于是也就又了下文。
大家都知道,其实轮播图的本质还是很简单的,就是在点击的时候,获得两个值,一个是当前包裹层的left值,一个是鼠标点击包裹层外面的展示层(也就是overflow:hidden的最外层)时的鼠标位置。这个包裹层的left值,如果想用offsetLeft的话,千万要记住直接在dom上取就好了,style上是没有的!!!,呀呀呀!我就被坑了足足五分钟,才想到!!!如果是left的话就在style上找就好了,left和offset在展示层设置了position之后,在做轮播图上没有什么区别,都是一样的。
但是,那个点击事件中的如果用了offsetX,那么酸爽的闪跳就要开始了!
mousedown = (e) => {this.flag = trueconst { offsetX: X } = e// 点击这个offsetX成了与img的left距离// const { pageX: X } = e// 先拿到了 container 相对于 页面 的 位置 x ythis.startX = X;this.startLeft = parseInt(this.mycontainer.offsetLeft || 0)// 这里选择offsetLeft 一直都取不到数值啊 原来不在style上啊 !!// this.startLeft = parseInt(this.mycontainer.style.left || 0)return false}
mousemove = (event) => {if (this.flag) {event.preventDefault()const { offsetX: moveX } = event // offsetX最大只是能200console.log("move offsetX", moveX)let offsetLeft = moveX - this.startX;this.mycontainer.style.left = `${-offsetLeft + this.startLeft}px`// 上面要注意 类型没有为整数时 直接字符串+字符串 也是闪跳的原因之一 }return false}
上面这个是addEventListener的两个函数,分别用于点击和移动。
闪跳的原因
闪跳的原因其实本质上就是left的忽然变大或者变小,围绕这个原因,我发现了两处很有可能发生left值突然的变化的地方。
第一个是,我一开始选择的是,在点击的时候,拿到left,但是left大家都知道,left拿到的是一个带px的字符串,我天真的以为把字符串“px”去掉了,然后字符串加上一个数字自动就会转化为数字了,结果出现了一下子left值变成了 34 + “34” = “3434” 这样的悲剧,关键当时我还像下图一样,加了一个Number,直接导致,图像瞬间移动,不过这个闪跳还是比较好发现的
this.mycontainer.style.left = `${Number(-offsetLeft + this.startLeft)}px`
第二个就是关于 offsetX的问题了,先来考考大家,offsetX的是鼠标到哪里的距离呢,绝大多数人,可能会回答就像是offsetLeft一样,是相对于其父级的,但是这个在event事件中的offsetX就是不成立的了,网上对于offsetX的描述非常少,但是我觉得一句话说得非常好,事件发生时鼠标相对于事件源元素的坐标,而这个源元素是什么呢?我觉得是event.target的那个,下面我将用这次自己出现的问题来验证这个源元素。

这个问题的出现,将直接影响一个效果,那就是闪跳,当你从左图点击时,你的初始化的startX为150px(假设),而当你鼠标滑动到右图时,你的move的moveX一下子变为了0,而这时的你的left在会突然有一个较大的变化值,所以就会发生闪跳。
PS:如果你将我的代码逻辑,改变一下,也就是图随之鼠标的移动而移动的话,只需要改变一行代码,即就是把下图的offsetLeft前面的负号去掉,这个offsetLeft是我设置的鼠标移动减去鼠标点击之后的偏移量,这样的话,不会出现我这个上面所展示的因为offsetX的源元素而导致的闪跳问题,但是也会出现图片移动过程中发抖,也就是offsetX获取的值会忽大忽小,原因也是比较简单,其实还是由于offsetX定位于img,所以img在移动的过程中,你的鼠标也在移动,如果你鼠标移动比较慢,因为,offsetX的计算应该与img有关,而img本身又会移动,所以会出现一些计算问题(当然这个是我比较粗浅的理解,大家可以自己尝试一下,这个抖动问题,因为我换成pageX,如果鼠标慢一点移动,确实基本没有抖动)。
this.mycontainer.style.left = `${offsetLeft + this.startLeft}px`
二、使用pageX
当我使用pageX的时候,由于pageX是相对于整个页面的鼠标事件中的横坐标位置,所以用来计算偏移量真的是很好的选择了,轮播图的移动也会比较丝滑,代码的话,就是把event事件中的所以offsetX换成pageX,嗯,非常好用!!!!
三、思考
我觉得,用offsetX真的会出现效率问题,因为offsetX每次都需要在img变化之后,再次计算,也有可能就是渲染时机进一步导致抖动的!!!而pageX则一直直接与窗口计算,应该效率会高很多!!!
















