欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

原生JavaScript實(shí)現(xiàn)滑動(dòng)拖動(dòng)驗(yàn)證的示例代碼

本文介紹了原生JavaScript實(shí)現(xiàn)滑動(dòng)拖動(dòng)驗(yàn)證的示例代碼,分享給大家,具體如下:

專業(yè)從事企業(yè)網(wǎng)站建設(shè)和網(wǎng)站設(shè)計(jì)服務(wù),包括網(wǎng)站建設(shè)、域名注冊、雅安服務(wù)器托管、企業(yè)郵箱、微信公眾號(hào)開發(fā)、微信支付寶成都微信小程序、app軟件開發(fā)公司、軟件開發(fā)、等服務(wù)。公司始終通過不懈的努力和以更高的目標(biāo)來要求自己,在不斷完善自身管理模式和提高技術(shù)研發(fā)能力的同時(shí),大力倡導(dǎo)推行新經(jīng)濟(jì)品牌戰(zhàn)略,促進(jìn)互聯(lián)網(wǎng)事業(yè)的發(fā)展。

原生JavaScript實(shí)現(xiàn)滑動(dòng)拖動(dòng)驗(yàn)證的示例代碼

通常,我們?yōu)榱朔乐褂脩魫阂馓峤槐韱?,?huì)讓用戶在提交前完成滑動(dòng)拖動(dòng)驗(yàn)證,有時(shí)候這也能起到一絲反爬的作用。

實(shí)現(xiàn)滑動(dòng)驗(yàn)證的方式當(dāng)然不止一種,這里我們直接使用原生 JavaScript 來實(shí)現(xiàn)。

現(xiàn)在,你可以在這里 看到完整的源碼。

原生實(shí)現(xiàn)

原生 JavaScript 的實(shí)現(xiàn),主要是通過監(jiān)聽鼠標(biāo)事件來對(duì) DOM 進(jìn)行一系列的操作。

滑塊驗(yàn)證的結(jié)構(gòu)主要分為四個(gè)部分:軌道、滑塊、背景和文案,我們可以使用下面的 HTML 結(jié)構(gòu)來表示。

<div class="slide-track">
 <div class="slide-bg"></div>
 <div class="slide-block"></div>
 <p class="slide-text">請按住滑塊,拖動(dòng)到最右邊</p>
</div>

基本思路就是我們給滑塊(.slide-block)添加相應(yīng)的事件,在按下滑塊時(shí)記錄鼠標(biāo)的當(dāng)前位置并添加滑動(dòng)事件,在滑動(dòng)過程中根據(jù)鼠標(biāo)的移動(dòng)來移動(dòng)滑塊的位置和增加背景元素(.slide-bg)的寬度,直到移動(dòng)到軌道(.slide-track)的末端后,改變文案(.slide-text)來提示成功。

樣式

在開始寫腳本之前可以先來完成一下它們的樣式,這讓滑塊相關(guān)的部分看起來更好,也讓后面的工作更愉快的進(jìn)行。

/* 樣式的注意事項(xiàng) */

樣式的寫法就不貼了,相信大家一看就懂,而且會(huì)有更好的實(shí)現(xiàn)。需要的話,也可以在 Github 上找到。

腳本

現(xiàn)在開始來實(shí)現(xiàn)腳本的內(nèi)容,首先我們對(duì) document.querySelector 方法進(jìn)行簡單的封裝以方便后續(xù)操作 DOM 元素。

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

然后通過自定義的 _h 函數(shù)我們可以很方便的創(chuàng)建上面的 HTML 結(jié)構(gòu),并添加到文檔中。

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 = { // 默認(rèn)配置
   tip: '請按住滑塊,拖動(dòng)到最右邊',
   unlockText: '驗(yàn)證成功',
   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)
 }
}

在創(chuàng)建好 DOM 結(jié)構(gòu)后,接下來為滑塊添加鼠標(biāo)按下的事件,在這個(gè)事件中我們需要記錄下鼠標(biāo)的初始橫坐標(biāo),以便后續(xù)和滑動(dòng)過程中的位置相比較,同時(shí)為其添加滑動(dòng)事件。

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) {}
}

在這里有點(diǎn)細(xì)節(jié)需要注意:

  • 首先,由于事件監(jiān)聽器中的 this 指向的是觸發(fā)事件的元素,為此我們在指定鼠標(biāo)按下的監(jiān)聽器時(shí)為其綁定了 this,以便調(diào)用滑塊實(shí)例屬性和原型上的方法。
  • 其次,我們在鼠標(biāo)按下的監(jiān)聽器中添加了鼠標(biāo)移動(dòng)的監(jiān)聽器,如果在初始時(shí)同按下的監(jiān)聽器一起指定,那么會(huì)先執(zhí)行鼠標(biāo)移動(dòng)的監(jiān)聽器,而此時(shí)并沒有記錄鼠標(biāo)的初始位置;

接下來我們要實(shí)現(xiàn)滑動(dòng)過程中的主要邏輯:根據(jù)鼠標(biāo)的移動(dòng)實(shí)時(shí)地更新滑塊的位置,并對(duì)一些臨界位置進(jìn)行處理。

_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) {
  // 當(dāng)鼠標(biāo)移開滑塊時(shí)取消移動(dòng)
  return
 }

 this.$$block.style.left = `${moveX}px` // 更新滑塊的我i之
 this.$$bg.style.width = `${moveX}px` // 同步增大背景元素的寬度

 // 當(dāng)滑塊滑動(dòng)的距離大于等于軌道除去滑塊寬度后的距離時(shí)表示已經(jīng)到達(dá)軌道的最右邊了
 if (moveX >= this.$$root.offsetWidth - (x2 - x1)) {
  this.$$isSuccess = true
  this.$$text.textContent = "驗(yàn)證成功"
  this.$$text.style.cssText = `color: #fff; left: 0; right: ${this.$$block.offsetWidth}px`
  this.$$block.classList.add("success")
 }
}

這里的實(shí)現(xiàn)也很簡單,唯一需要看一下的就是通過 getBoundingClientRect 來獲取了滑塊相對(duì)于視口的位置,然后根據(jù)鼠標(biāo)所在的位置來判斷鼠標(biāo)是否在滑塊上,如果不在則取消移動(dòng)。

現(xiàn)在它已經(jīng)能很好的滑動(dòng),并完成提示成功的基本功能了。但是,當(dāng)我們每次滑動(dòng)到中間就取消,然后再次點(diǎn)擊滑動(dòng)時(shí),就會(huì)導(dǎo)致重復(fù)的添加滑動(dòng)事件,而且中途釋放后,滑塊就停在了當(dāng)前位置,這顯然不對(duì)。

解決的辦法就是在添加鼠標(biāo)按下事件的時(shí)候,同時(shí)也指定一個(gè)松開的事件,在這個(gè)事件的監(jiān)聽器中判斷如果沒有成功則取消之前綁定的滑動(dòng)事件,并進(jìn)行重置,為了看起來更友好,我們還可以加上一點(diǎn)動(dòng)畫。

class SlideUnlock {
 init() {
  /* ... */
  document.addEventListener(
   "mouseup",
   (this.$$handleMouseUp = this._handleMouseUp.bind(this)),
   false
  )
 }

 _handleMouseDown(e) {
  /* ... */
  // 取消在手動(dòng)滑動(dòng)過程中的動(dòng)畫效果
  this.$$bg.style.transition = ""
  this.$$block.style.transition = ""
  /* ... */
 }

 _handleMouseUp(e) {
  this.$$block.removeEventListener(
   "mousemove",
   this.$$handleMouseMove,
   false
  )

  if (this.$$isSuccess) {
   return
  }

  // 給重置過程添加動(dòng)畫效果
  this.$$bg.style.transition = "width 1s ease"
  this.$$block.style.transition = "left 1s ease"

  this.$$block.style.left = 0
  this.$$bg.style.width = 0
 }
}

目前為止,滑塊已經(jīng)可以在 PC 端正常的工作了,不過在移動(dòng)端卻并不理想。

為了它能夠在移動(dòng)端也可以很好的工作,我們可以借助 touchstarttouchmove、touchend 等事件來完成。

綁定這些事件的時(shí)機(jī)和處理方式和之前的三個(gè)事件分別相對(duì)應(yīng),所以我們新增兩個(gè)方法(和 jQuery 的 on、off 方法很像)來更好的添加和移除事件。

function bindEvents(events, handler, element = $("body")) {
 events.split(" ").forEach(event => {
  element.addEventListener(event, handler, false)
 })
}

function unbindEvents(events, handler, element = $("body")) {
 events.split(" ").forEach(event => {
  element.removeEventListener(event, handler, false)
 })
}

根據(jù)這兩個(gè)方法,我們來稍微修改一下滑塊中添加事件的代碼。

function bindEvents(events, handler, element = $("body")) {
 events.split(" ").forEach(event => {
  element.addEventListener(event, handler, false)
 })
}

function unbindEvents(events, handler, element = $("body")) {
 events.split(" ").forEach(event => {
  element.removeEventListener(event, handler, false)
 })
}

另外,需要注意的是在移動(dòng)端 touch 事件中獲取 clientX、clientY 時(shí)不能在事件對(duì)象上直接讀取,而是在 event.changedTouches[0] 對(duì)象上取得。

現(xiàn)在,它已經(jīng)能夠同時(shí)在 PC 端和移動(dòng)端上工作了,不過我們還能對(duì)它進(jìn)行一些優(yōu)化,比如使用函數(shù)節(jié)流。

函數(shù)節(jié)流的實(shí)現(xiàn)方式有很多,這里列一下我們在本次過程中使用的方式。

utils.throttle = function(method, context = {}, delay = 4, ...outParams) {
 return function(...innerParams) {
 clearTimeout(context.$$tId)
 context.$$tId = setTimeout(function() {
  method.apply(context, [...outParams, ...innerParams])
 }, delay)
 }
}

然后用這個(gè)節(jié)流函數(shù),來包裝我們移動(dòng)時(shí)的處理函數(shù),并根據(jù)實(shí)際情況做點(diǎn)調(diào)整。

除此之外,我們還可以添加一個(gè)重置的方法,讓它回到最初的狀態(tài),涉及到的內(nèi)容也很簡單,就是在成功的狀態(tài)下重新設(shè)置樣式和綁定事件。

reset() {
 if (!this.$$isSuccess) {
  return
 }
 this.$$isSuccess = false
 this.$$bg.style.cssText =
  `transition: width ${this.$options.duration}ms ease; width: 0;`
 this.$$block.style.cssText =
  `transition: left ${this.$options.duration}ms ease; left: 0;`
 this.$$text.style.cssText =
  `color: #5f5f5f; left: ${this.$$block.offsetWidth}px; right: 0;`
 this.$$text.textContent = this.$options.tip
 this.$$block.classList.remove("success")
 this._bindEvents()
}

好了,滑塊的實(shí)現(xiàn)到這里就告一段落了,相信大家看到這里已經(jīng)完全明白了,甚至有更好的實(shí)現(xiàn)。

如何使用

你可以簡單的在 HTML 頁面中引入該腳本,然后根據(jù)自己的需求設(shè)置合適的樣式;不過更好的方式是通過這樣的思路,在項(xiàng)目中做一些改進(jìn)(比如平滑降級(jí))等處理。

接下來是一個(gè)簡單的使用模板。

<body>
 <script src="slide-unlock/core.js"></script>
 <script>
  const slider = new SlideUnlock()
  slider.init()
 </script>
</body>

你可以在 這里 看見完整的使用方式和效果。

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

本文題目:原生JavaScript實(shí)現(xiàn)滑動(dòng)拖動(dòng)驗(yàn)證的示例代碼
網(wǎng)站URL:http://aaarwkj.com/article10/jjgjgo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供ChatGPT、微信公眾號(hào)、App開發(fā)、標(biāo)簽優(yōu)化品牌網(wǎng)站設(shè)計(jì)、虛擬主機(jī)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司
中文字幕一区二区三区不卡日日| 99久久久精品国产免费| 国产青青草成人在线视频| 偷窥偷拍视频一区二区| 日韩精品人成在线播放| 成人黄网站色大片免费| 亚洲中文字幕乱码丝袜在线精品| 欧美香蕉高清视频免费| 五月婷婷丁香综合中文字幕| 未满十八禁止观看免费| 国产黄a三级三级三级老师绑| 亚洲一区二区视频在线观看免费 | 欧美小黄片在线免费看| 亚洲国内精品一区二区在线| 丰满人妻被黑人猛烈进入| 国产三级黄色片免费看| 日本精彩视频一区二区| 国产aaa级日本一区二区三区| 九七青青草视频在线观看| 麻豆人妻少妇精品毛片| 亚洲av综合色区一区| 人妻久久一区二区三区精品99| 精品av一区二区在线| 久久人婷婷人人澡人人爽| 国产精品1区2区久久久| 亚洲乱人伦一区二区三区| 成人福利在线观看免费视频| 国产在线观看一区二区三区精品| 国产黄色三级电影在线| 高h视频在线播放观看| 久久久久精品国产亚洲av影院| 亚洲国产韩国精品在线| 久久亚洲第一视频网站| 精精国产xxxx视频在线不卡| 2020年最新国产三级网站| 日韩不卡一区二区三区| 青青草原一区二区三区| 亚洲国产视频不卡一区| 国产l精品国产亚洲区久久 | 精品国产熟女成人av| 亚洲精品熟女国产中文|