最近一直在忙项目,很少有时间回顾之前的知识,今天刚好要做一个轮播,因为对兼容性有一定的要求,使用了各种插件和库中的轮播,效果都不是很理想,一怒之下,使用原生JS封装了一个轮播组件,其中重要的功能就是一个动画,看了一下以前封装的函数,千疮百孔,又进行了重新封装,先上代码,有详细的备注。
function animate(el, target, step, dtime) { /** * 参数说明: * - el 表示操作的元素对象 * - target 表示移动的目标距离 单位 px * - step 表示步长,即每次移动的距离 单位 px * - dtime 表示移动的间隔时间 单位 ms */ // 步长和间隔时间设置了默认值 step = step || 10; dtime = dtime || 30; // 判断是否开启定时器,如果有就清除 if (el.timeId) { clearInterval(el.timeId); el.timeId = null; }; // 开启一个定时器,并将定时器挂载道当前元素上 el.timeId = setInterval(function () { /** * 获取盒子移动前的水平方向的位置(当前位置) - 偏移的位置 * - 可以使用 el.offsetLeft 获取,但会将外边距也获取到,不精准,不采用 * - 这里移动实现方式是改变 left的值,保持统一,还是使用 el.style.left 获取 * - 使用 el.style.left 有个弊端是,若元素对象上最初没有 left 属性时,获取返回的是 NAN * - 这种情况只有在第一次会出现,故最开始的时候,还需要判断返回的值,若为 NAN,则重置为 0;如下 */ var current = parseInt(el.style.left); current = current ? current : 0; // 判断目标距离是否小于当前位置,若小于将 步长 变为 负数,让元素反着移动 if (current > target) { step = -Math.abs(step); } // 当目标距离与当前位置的差距小于步长时,直接当目标的水平位置设置为目标距离,并清除定时器后跳出函数 if (Math.abs(current - target) < Math.abs(step)) { clearInterval(el.timeId); el.style.left = target + 'px'; return; } // 定时器每执行一次,就让元素移动一个 步长 el.style.left = current + step + 'px'; }, dtime) }
有两个地方需要特别说明:
- 计时器的是直接挂载到被操作的元素对象上的
el.timeID
方便复用 - 获取当前水平偏移位置时,没使用 offsetLeft,因为当元素存在外边距时会产生误差,故还时使用原生获取left 的,并对不存在的问题做了判断处理。
若有不足或有更好建议的,欢迎留言交流。
来源:https://www.cnblogs.com/pingzx/p/10892429.html