原生JavaScript实现滑动拖动验证的示例代码

原生JavaScript实现滑动拖动验证的示例代码

通常,我们为了防止用户恶意提交表单,会让用户在提交前完成滑动拖动验证,有时候这也能起到一丝反爬的作用。

实现滑动验证的方式当然不止一种,这里我们直接使用原生 JavaScript 来实现。

现在,你可以在这里 看到完整的源码。

原生实现

原生 JavaScript 的实现,主要是通过监听鼠标事件来对 DOM 进行一系列的操作。

滑块验证的结构主要分为四个部分:轨道、滑块、背景和文案,我们可以使用下面的 HTML 结构来表示。

<div> <div></div> <div></div> <p>请按住滑块,拖动到最右边</p> </div>

基本思路就是我们给滑块(.slide-block)添加相应的事件,在按下滑块时记录鼠标的当前位置并添加滑动事件,在滑动过程中根据鼠标的移动来移动滑块的位置和增加背景元素(.slide-bg)的宽度,直到移动到轨道(.slide-track)的末端后,改变文案(.slide-text)来提示成功。

样式

在开始写脚本之前可以先来完成一下它们的样式,这让滑块相关的部分看起来更好,也让后面的工作更愉快的进行。

/* 样式的注意事项 */

样式的写法就不贴了,相信大家一看就懂,而且会有更好的实现。需要的话,也可以在 Github 上找到。

脚本

现在开始来实现脚本的内容,首先我们对 document.querySelector 方法进行简单的封装以方便后续操作 DOM 元素。

function $(selectors) { return document.querySelector(selectors); }

然后通过自定义的 _h 函数我们可以很方便的创建上面的 HTML 结构,并添加到文档中。

function _h(tagName, propMap = {}, text) { const ele = document.createElement(tagName); Object.keys(propMap).forEach(prop => ele.setAttribute(prop, propMap[prop])); if (text) { ele.appendChild(document.createTextNode(text)); } return ele; } class SlideUnlock { constructor(el = "body", options = {}) { this.$el = $(el) this.$$isSuccess = false this.$options = { // 默认配置 tip: '请按住滑块,拖动到最右边', unlockText: '验证成功', duration: 500, ...options } } init() { this.$$root = _h("div", { class: "slide-track" }) // 轨道 this.$$bg = this.$$root.appendChild(_h("div", { class: "slide-bg" })) this.$$block = this.$$root.appendChild( _h("div", { class: "slide-block" }) // 滑块 ) this.$$text = this.$$root.appendChild( _h("p", { class: "slide-text" }, this.$options.tip) ) this.$el.insertBefore(this.$$root, this.$el.firstChild) } }

在创建好 DOM 结构后,接下来为滑块添加鼠标按下的事件,在这个事件中我们需要记录下鼠标的初始横坐标,以便后续和滑动过程中的位置相比较,同时为其添加滑动事件。

class SlideUnlock { init() { /* ... */ this.$$block.addEventListener( "mousedown", (this.$$handleMouseDown = this._handleMouseDown.bind(this)), false ) } _handleMouseDown(e) { const downx = e.clientX e.target.addEventListener( "mousemove", (this.$$handleMouseMove = this._handleMouseMove.bind(this, downx)), false ) e.preventDefault() } _handleMouseMove(downx, e) {} }

在这里有点细节需要注意:

首先,由于事件监听器中的 this 指向的是触发事件的元素,为此我们在指定鼠标按下的监听器时为其绑定了 this,以便调用滑块实例属性和原型上的方法。

其次,我们在鼠标按下的监听器中添加了鼠标移动的监听器,如果在初始时同按下的监听器一起指定,那么会先执行鼠标移动的监听器,而此时并没有记录鼠标的初始位置;

接下来我们要实现滑动过程中的主要逻辑:根据鼠标的移动实时地更新滑块的位置,并对一些临界位置进行处理。

_handleMouseMove(downx, e) { const info = this.$$block.getBoundingClientRect(), x = e.clientX, y = e.clientY, x1 = info.left, y1 = info.top, x2 = info.right, y2 = info.bottom, moveX = x - downx if (this.$$isSuccess) { return } if (moveX < 0) { return } if (x < x1 || x > x2 || y < y1 || y > y2) { // 当鼠标移开滑块时取消移动 return } this.$$block.style.left = `${moveX}px` // 更新滑块的我i之 this.$$bg.style.width = `${moveX}px` // 同步增大背景元素的宽度 // 当滑块滑动的距离大于等于轨道除去滑块宽度后的距离时表示已经到达轨道的最右边了 if (moveX >= this.$$root.offsetWidth - (x2 - x1)) { this.$$isSuccess = true this.$$text.textContent = "验证成功" this.$$text.style.cssText = `color: #fff; left: 0; right: ${this.$$block.offsetWidth}px` this.$$block.classList.add("success") } }

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

转载注明出处:http://www.heiqu.com/27ccd7f97aaf7ade7d88653e1b048986.html