成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

移動(dòng)端手勢(shì)庫設(shè)計(jì)與實(shí)踐

wudengzan / 3624人閱讀

摘要:前言本次給大家分享的是常見的移動(dòng)端單點(diǎn)觸摸事件的設(shè)計(jì)思路及實(shí)踐。實(shí)現(xiàn)即手指滑動(dòng)事件,應(yīng)用場(chǎng)景如輪播圖左右滑動(dòng)切換,整屏頁面滑動(dòng)翻頁等,算是移動(dòng)端最常見的手勢(shì)之一了。

前言

本次給大家分享的是常見的移動(dòng)端單點(diǎn)觸摸事件的設(shè)計(jì)思路及實(shí)踐。

核心技術(shù)

主要就是利用移動(dòng)端的以下3個(gè)觸摸事件,來模擬和實(shí)現(xiàn)自定義的手勢(shì)操作

touchstart:手指觸摸到屏幕的一瞬間觸發(fā)

touchmove:手指在屏幕上移動(dòng)時(shí)觸發(fā)

touchend:手指從屏幕上離開時(shí)觸發(fā)

概念梳理

touch事件觸發(fā)時(shí),有3組數(shù)據(jù)可以獲得觸摸信息,可能大家會(huì)對(duì)這幾組數(shù)據(jù)有些混淆,我根據(jù)自己的理解來盡量用通俗的語言給大家解釋清楚

touches:整個(gè)屏幕上所有的觸摸點(diǎn)集合

targetTouches:當(dāng)前DOM元素上的所有觸摸點(diǎn)集合

changedTouches:相對(duì)上一次觸摸點(diǎn)發(fā)生變化的集合

我們先來看一張圖

如圖所示,我們?cè)诠?jié)點(diǎn)B上綁定touch事件,圓圈代表觸摸點(diǎn)。

此時(shí)節(jié)點(diǎn)B有3個(gè)觸摸點(diǎn),即targetTouches數(shù)組有3項(xiàng),分別儲(chǔ)存著觸摸點(diǎn)的信息,此時(shí)touchestargetTouches是相同的。

當(dāng)我們將手指3移出節(jié)點(diǎn)B(始終保持3個(gè)手指觸摸在屏幕上),那么touchmove事件觸發(fā),targetTouches只剩2項(xiàng),而touches依然有3項(xiàng),此時(shí)changedTouches只有一項(xiàng)(因?yàn)橹挥惺种?改變了)。

然后我們讓所有手指離開屏幕,那么此時(shí)touchend事件觸發(fā),touches只剩0項(xiàng),targetTouches剩0項(xiàng),changedTouches有3項(xiàng)(因?yàn)?個(gè)手指發(fā)生了變化)。

好了,理解這些概念,有助于我們理解代碼中何時(shí)改去哪個(gè)touch數(shù)組里面的值。

思路及實(shí)踐 tap

tap可以理解為點(diǎn)擊事件,和click不同的是,移動(dòng)端的click事件有大約300ms的延遲,這是因?yàn)闉g覽器要判斷是否為雙擊事件。

思路

touchstart:時(shí)記錄時(shí)間點(diǎn)以及觸摸點(diǎn)的x、y坐標(biāo)

touchend:計(jì)算此時(shí)與開始時(shí)的時(shí)間差,水平和垂直方向的偏移量

說明:時(shí)間差用來判斷用戶觸摸的時(shí)長,超過規(guī)定時(shí)間則tap事件無效;偏移量用來判斷用戶的觸摸事件內(nèi)是否有過移動(dòng)的痕跡,這里我們?cè)试S少量的偏移,因?yàn)槭种缚赡艹霈F(xiàn)抖動(dòng)的情況

實(shí)現(xiàn)

const tapDefaults = {
  time: 250,
  offset: 10
}

export default function tap (node, a, b) {
  let st, sx, sy
  let opts, callback

  if (typeof a === "function") {
    callback = a
    opts = Object.assign({}, tapDefaults, b)
  } else {
    callback = b
    opts = Object.assign({}, tapDefaults, a)
  }

  node.addEventListener("touchstart", (e) => {
    e.preventDefault() // 組織瀏覽器默認(rèn)行為,防止觸摸過程頁面滾動(dòng)

    const touch = e.targetTouches[0]
    st = e.timeStamp
    sx = touch.pageX
    sy = touch.pageY
  }, false)

  node.addEventListener("touchend", (e) => {
    const touch = e.changedTouches[0]

    if (
      // 若為長按,則將時(shí)間判定條件更改
      e.timeStamp - st <= opts.time &&
      Math.abs(touch.pageX - sx) <= opts.offset &&
      Math.abs(touch.pageY - sy) <= opts.offset
    ) {
      callback && callback()
    }
  }, false)
}
doubletap

即雙擊事件,兩次點(diǎn)擊時(shí)間間隔不超過規(guī)定時(shí)間則視為有效。

思路

第一次有效點(diǎn)擊,記錄該狀態(tài),反之重置狀態(tài)

第二次有效點(diǎn)擊,觸發(fā)事件并重置狀態(tài)

若兩次時(shí)間間隔過長,重置狀態(tài)

實(shí)現(xiàn)

const tapDefaults = {
  time: 250,
  offset: 10
}

function handler (node, inject) {
  let st, sx, sy

  node.addEventListener("touchstart", (e) => {
    e.preventDefault()

    const touch = e.targetTouches[0]
    st = e.timeStamp
    sx = touch.pageX
    sy = touch.pageY
  }, false)

  node.addEventListener("touchend", (e) => {
    const touch = e.changedTouches[0]

    inject({
      time: e.timeStamp - st,
      offsetX: Math.abs(touch.pageX - sx),
      offsetY: Math.abs(touch.pageY - sy)
    })
  }, false)
}

export function doubletap (node, a, b) {
  let opts, callback
  let status = 0

  if (typeof a === "function") {
    callback = a
    opts = Object.assign({}, tapDefaults, b)
  } else {
    callback = b
    opts = Object.assign({}, tapDefaults, a)
  }

  handler(node, (info) => {
    if (
      info.time <= opts.time &&
      info.offsetX <= opts.offset &&
      info.offsetY <= opts.offset
    ) {
      if (status === 0) {
        status = 1
        // 時(shí)間間隔太長則重置狀態(tài)
        setTimeout(() => {
          status = 0
        }, opts.time)
      } else if (status === 1) {
        callback && callback()
        status = 0
      }
    } else {
      status = 0
    }
  })
}
longtap

即長按,手指按住超過規(guī)定時(shí)間視為有效,在手指離開時(shí)觸發(fā)。

思路

和tap事件思路一樣,只不過時(shí)間的判定條件變更一下,改為超過多長時(shí)間才觸發(fā)

實(shí)現(xiàn)

const longtapDefaults = {
  time: 350,
  offset: 10
}

// 這里代碼邏輯和tap事件一樣
// 更改時(shí)間判定為:
// e.timeStamp - st > opts.time
press

即按壓事件,按住超過規(guī)定時(shí)間自動(dòng)觸發(fā),注意和longtap不同的是,longtap需要等到手指離開時(shí)觸發(fā),而press在按壓時(shí)間達(dá)到規(guī)定值,自動(dòng)觸發(fā),此時(shí)手指還在屏幕上。

思路

touchstart:記錄此時(shí)的x、y坐標(biāo),并且開啟一個(gè)定時(shí)器,在規(guī)定時(shí)間后執(zhí)行回調(diào),默認(rèn)是350ms

touchmove:監(jiān)聽移動(dòng)過程,在事件觸發(fā)前,若出現(xiàn)偏移量過大,則取消定時(shí)器

touchend:取消定時(shí)器

分析:根據(jù)以上思路,若按壓時(shí)間短,則手指離開時(shí)定時(shí)器已取消,回調(diào)不會(huì)觸發(fā)。

實(shí)現(xiàn)

const pressDefaults = {
  time: 350,
  offset: 10
}

export default function press (node, a, b) {
  let opts, callback, sx, sy
  let timer = null

  if (typeof a === "function") {
    callback = a
    opts = Object.assign({}, pressDefaults, b)
  } else {
    callback = b
    opts = Object.assign({}, pressDefaults, a)
  }

  node.addEventListener("touchstart", (e) => {
    e.preventDefault()

    const touch = e.targetTouches[0]
    sx = touch.pageX
    sy = touch.pageY

    timer = setTimeout(() => {
      callback && callback()
    }, opts.time)
  }, false)

  node.addEventListener("touchmove", (e) => {
    const touch = e.targetTouches[0]

    if (
      Math.abs(touch.pageX - sx) > opts.offset ||
      Math.abs(touch.pageY - sy) > opts.offset
    ) {
      clearTimeout(timer)
    }
  }, false)

  node.addEventListener("touchend", () => {
    clearTimeout(timer)
  }, false)
}
swipe

即手指滑動(dòng)事件,應(yīng)用場(chǎng)景如:輪播圖左右滑動(dòng)切換,整屏頁面滑動(dòng)翻頁等,算是移動(dòng)端最常見的手勢(shì)之一了。

思路

touchstart:記錄時(shí)間點(diǎn)和觸摸點(diǎn)位置

touchmove:實(shí)時(shí)判斷滑動(dòng)偏移量

touchend:計(jì)算滑動(dòng)速度和方向,條件判定是否觸發(fā)事件

分析:考慮到需要在滑動(dòng)過程做一些動(dòng)畫特效等操作,因此我們將滑動(dòng)中的事件暴露給用戶自定義,值得注意的是,若是要實(shí)時(shí)改變滑塊位置的話,最好不要截流或防抖,截流會(huì)造成滑動(dòng)卡頓的現(xiàn)象,而防抖會(huì)出現(xiàn)延遲同步滑動(dòng)操作的情況;另外對(duì)滑動(dòng)速度也進(jìn)行了處理,原則上用戶滑動(dòng)距離超過規(guī)定后即視為有效,然而為了更好的用戶體驗(yàn),我們判定,如果用戶在短時(shí)間內(nèi)滑動(dòng)速度非??斓脑挘惨暈橐淮斡行У牟僮?,不一定非要滑動(dòng)很長的距離

實(shí)現(xiàn)

const swipeDefaults = {
  direction: "horizontal", // vertical
  speed: 200,
  offset: 100,
  prevent: true,
  // touchmove: (offset) => {}
}

export default function swipe (node, a, b) {
  let opts, callback, sTime, sTouch, eTouch

  if (typeof a === "function") {
    callback = a
    opts = Object.assign({}, swipeDefaults, b)
  } else {
    callback = b
    opts = Object.assign({}, swipeDefaults, a)
  }

  node.addEventListener("touchstart", (e) => {
    if (opts.prevent) {
      e.preventDefault()
    }

    sTime = e.timeStamp
    sTouch = eTouch = e.targetTouches[0]
  }, false)

  if (typeof opts.touchmove === "function") {
    node.addEventListener("touchmove", (e) => {
      eTouch = e.targetTouches[0]

      if (opts.direction === "horizontal") {
        opts.touchmove(eTouch.pageX - sTouch.pageX)
      } else {
        opts.touchmove(eTouch.pageY - sTouch.pageY)
      }
    }, false)
  }

  node.addEventListener("touchend", (e) => {
    eTouch = e.changedTouches[0]

    let time = e.timeStamp - sTime
    let offset, direction

    if (opts.direction === "horizontal") {
      offset = eTouch.pageX - sTouch.pageX
      direction = offset > 0 ? "right" : "left"
    } else {
      offset = eTouch.pageY - sTouch.pageY
      direction = offset > 0 ? "down" : "up"
    }

    if (
      Math.abs(offset) >= opts.offset ||
      Math.abs(offset) / time * 1000 >= opts.speed
    ) {
      callback && callback(direction)
    }
  }, false)
}
結(jié)束語

通過以上的思路講解和代碼實(shí)現(xiàn),我們完成了一個(gè)單點(diǎn)觸控的移動(dòng)端手勢(shì)庫,是不是迫不及待的想要一睹為快、體驗(yàn)一番。

最后附上本次分享的源碼和文檔:https://github.com/ansenhuang/axe/blob/master/packages/touch/README.md

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/93723.html

相關(guān)文章

  • HTML5中手勢(shì)原理分析數(shù)學(xué)知識(shí)的實(shí)踐

    摘要:中手勢(shì)原理分析與數(shù)學(xué)知識(shí)的實(shí)踐引言在這觸控屏的時(shí)代,人性化的手勢(shì)操作已經(jīng)深入了我們生活的每個(gè)部分。這篇博文主要是解析了移動(dòng)端常用手勢(shì)的原理,及從前端的角度學(xué)習(xí)過程中所使用的數(shù)學(xué)知識(shí)。 HTML5中手勢(shì)原理分析與數(shù)學(xué)知識(shí)的實(shí)踐 引言 在這觸控屏的時(shí)代,人性化的手勢(shì)操作已經(jīng)深入了我們生活的每個(gè)部分?,F(xiàn)代應(yīng)用越來越重視與用戶的交互及體驗(yàn),手勢(shì)是最直接且最為有效的交互方式,一個(gè)好的手勢(shì)交互,能...

    rollback 評(píng)論0 收藏0
  • vue 在移動(dòng)體驗(yàn)上的優(yōu)化解決方案

    摘要:去年年底自己搭了一個(gè)在移動(dòng)端的開發(fā)框架,感覺體驗(yàn)不是很好。路由懶加載首頁終于寫完了,以上這些就是我在移動(dòng)端體驗(yàn)優(yōu)化的實(shí)戰(zhàn)。去年年底自己搭了一個(gè)vue在移動(dòng)端的開發(fā)框架,感覺體驗(yàn)不是很好。上個(gè)星期又要做移動(dòng)端的項(xiàng)目了。所以我花了兩天時(shí)間對(duì)之前的那個(gè)開發(fā)框架做了以下優(yōu)化 自定義vuex-plugins-loading 路由切換動(dòng)畫 + keep alive 動(dòng)態(tài)管理緩存組件 better-sc...

    godlong_X 評(píng)論0 收藏0
  • 單點(diǎn)手勢(shì)

    摘要:單點(diǎn)手勢(shì)庫分析手勢(shì)是什么有哪些方法實(shí)現(xiàn)首先我這里指的手勢(shì)是指我們?cè)谝苿?dòng)端進(jìn)行觸屏交互的時(shí)候,用戶操作的一些手勢(shì)??梢钥吹刂房偨Y(jié)這是我挺久之前做的移動(dòng)端單點(diǎn)手勢(shì)庫學(xué)習(xí)時(shí)參考劇中人你可以在這里找到我個(gè)人網(wǎng)站 單點(diǎn)手勢(shì)庫 分析 手勢(shì)是什么? 有哪些方法實(shí)現(xiàn)? 首先我這里指的手勢(shì)是指我們?cè)谝苿?dòng)端進(jìn)行觸屏交互的時(shí)候,用戶操作的一些手勢(shì)。在我們?cè)谝苿?dòng)端需要一些交互的時(shí)候。難免有時(shí)候需要左滑右...

    jollywing 評(píng)論0 收藏0
  • 單點(diǎn)手勢(shì)

    摘要:單點(diǎn)手勢(shì)庫分析手勢(shì)是什么有哪些方法實(shí)現(xiàn)首先我這里指的手勢(shì)是指我們?cè)谝苿?dòng)端進(jìn)行觸屏交互的時(shí)候,用戶操作的一些手勢(shì)??梢钥吹刂房偨Y(jié)這是我挺久之前做的移動(dòng)端單點(diǎn)手勢(shì)庫學(xué)習(xí)時(shí)參考劇中人你可以在這里找到我個(gè)人網(wǎng)站 單點(diǎn)手勢(shì)庫 分析 手勢(shì)是什么? 有哪些方法實(shí)現(xiàn)? 首先我這里指的手勢(shì)是指我們?cè)谝苿?dòng)端進(jìn)行觸屏交互的時(shí)候,用戶操作的一些手勢(shì)。在我們?cè)谝苿?dòng)端需要一些交互的時(shí)候。難免有時(shí)候需要左滑右...

    FuisonDesign 評(píng)論0 收藏0
  • 單點(diǎn)手勢(shì)簡單思考實(shí)現(xiàn)

    摘要:單點(diǎn)手勢(shì)庫分析手勢(shì)是什么有哪些方法實(shí)現(xiàn)首先我這里指的手勢(shì)是指我們?cè)谝苿?dòng)端進(jìn)行觸屏交互的時(shí)候,用戶操作的一些手勢(shì)??梢钥吹刂房偨Y(jié)這是我挺久之前做的移動(dòng)端單點(diǎn)手勢(shì)庫個(gè)人博客地址學(xué)習(xí)時(shí)參考劇中人 單點(diǎn)手勢(shì)庫 分析 手勢(shì)是什么? 有哪些方法實(shí)現(xiàn)? 首先我這里指的手勢(shì)是指我們?cè)谝苿?dòng)端進(jìn)行觸屏交互的時(shí)候,用戶操作的一些手勢(shì)。在我們?cè)谝苿?dòng)端需要一些交互的時(shí)候。難免有時(shí)候需要左滑右滑。 目前市面...

    ybak 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<