天天看點

前端JS H5 touch事件封裝,更加高效的開發移動端 - 戴向天

前端JS H5 touch事件封裝,更加高效的開發移動端 - 戴向天

大家好!我叫戴向天。今天我給大家分享一個我自己封裝的H5 touch事件的封裝。

該方法的使用特别的簡單,廢話不多說。先上代碼 ↓↓↓↓↓

/* 給元素綁定事件 /

function touch({dom, start, move, end, stop = true, change}) {
    const f = {
      data: {},
      start(e) {                        //手指觸碰的螢幕就會觸發(一次)
        stop && e.preventDefault()        //阻止冒泡,當stop為false的時候就運作冒泡,預設為true
        f.data = {                        //儲存的是一些資料
          ...f.data,                    //擴充運算,将之前的資料進行合并
          x: e.touches[0].pageX,        //手指開始的橫向位置
          y: e.touches[0].pageY,        //手指開始的縱向位置
          ex: 0,                        //手指結束的橫向位置
          ey: 0,                        //手指結束的縱向位置
          time: new Date().getTime(),    //手指的開始時間
        }
        start && start(f.data)        //執行自定義的 start 方法
      },
      move(e) {                    //多次
        stop && e.preventDefault()        //阻止冒泡,當stop為false的時候就運作冒泡,預設為true
        f.data = {                //儲存的是一些資料
          ...f.data,            //擴充運算,将之前的資料進行合并
          ex: e.touches[0].pageX,            //手指結束的橫向位置
          ey: e.touches[0].pageY,            //手指結束的縱向位置
        }
        move && move({                    //執行自定義的 move方法,并且把得到的資料進行傳回
          x: e.touches[0].pageX,
          y: e.touches[0].pageY,
          dx: f.data.ex - f.data.x,
          dy: f.data.ey - f.data.y
        })
      },
      end(e) {                //手指離開螢幕就會觸發(一次)
        stop && e.preventDefault()        //阻止冒泡,當stop為false的時候就運作冒泡,預設為true
        let time = new Date().getTime()    //手指離開的時間
        end && end({                //執行自定義的 end 方法,并且把得到的資料進行傳回
          time,                    //目前時間
          startTime: f.data.time,        //手指的開始時間
          dt: time - f.data.time,            //手指在螢幕逗留的時間差 ms
          dy: (f.data.ey || f.data.y) - f.data.y,        //手指在螢幕上的縱向的移動距離
          dx: (f.data.ex || f.data.x) - f.data.x        //手指在螢幕上的橫向的移動距離
        })
        
        // ↓ 下面的就是執行判斷手指移動的方向,當達到條件,就會執行change事件,
        // change 傳回的參數 
        //      direction: left | right | up | down | origin
        if (new Date().getTime() - f.data.time < 300) {        // 手指開螢幕上的時間很短

          if (Math.abs(f.data.ex - f.data.x) > 20 && Math.abs(f.data.ex - f.data.x) > Math.abs(f.data.ey - f.data.y)) {
            if (change) {
              if (f.data.ex > f.data.x) {
                change({
                  direction: 'right'
                })
              } else if (f.data.ex < f.data.x) {
                change({
                  direction: 'left'
                })
              }
            }
          } else if (Math.abs(f.data.ey - f.data.y) > 20 && Math.abs(f.data.ex - f.data.x) < Math.abs(f.data.ey - f.data.y)) {
            if (change) {
              if (f.data.ey > f.data.y) {
                change({
                  direction: 'down'
                })
              } else if (f.data.ey < f.data.y) {
                change({
                  direction: 'up'
                })
              }
            }
          } else {
            change && change({
              direction: 'origin'
            })
          }
        } else if (Math.abs(f.data.ey - f.data.y) >= 50) {
          if (change) {
            if (f.data.ey > f.data.y) {
              change({
                direction: 'down'
              })
            } else if (f.data.ey < f.data.y) {
              change({
                direction: 'up'
              })
            }
          }
        } else if (Math.abs(f.data.ex - f.data.x) >= 50) {
          if (change) {
            if (f.data.ex > f.data.x) {
              change({
                direction: 'right'
              })
            } else if (f.data.ex < f.data.x) {
              change({
                direction: 'left'
              })
            }
          }
        } else {
          change && change({
            direction: 'origin'
          })
        }
      }
    }
    // 這裡是防止dom元素綁定事件異常,導緻整體頁面無法正常往下執行
    try {
      dom.removeEventListener('touchstart', f.start)
      dom.addEventListener('touchstart', f.start)
      dom.removeEventListener('touchmove', f.move)
      dom.addEventListener('touchmove', f.move)
      dom.removeEventListener('touchend', f.end)
      dom.addEventListener('touchend', f.end)
    } catch (e) {
      console.error('給dom元素綁定事件的時候出現了錯誤', e)
    }
  }
           

下面我寫了一個案例的vue檔案 按鈕組的元件

裡面的style代碼是我在我寫的公共樣式裡面進行提取出來的。

dd-img元件其實就是一個圖檔自适應的元件。 該元件内類容在上篇文章有過描述

v-if="config.buttons.length>0">
<div class="flex" ref="ddBanner" style="transform: translateX(0px);"
     :style="{'width':7.5 * getBtsGroup(config.buttons).length + 'rem'}">
  <div v-for="(buttonList,chunkBtnKey) in getBtsGroup(config.buttons)" :key="chunkBtnKey">
    <ul class="flex-wrap flex w-750" :class="config.className">
      <li class="w20 t-c pad-b-10"
          v-for="(item,key) in buttonList"
          :key="key"
          :class="item.parentClass"
          @click.stop="handle(item)"
      >
        <div
          :class="item.class"
          :style="item.style"
        >
          <dd-img v-if="item.src" class="mar-a mar-b-10" :src="item.src" :width="0.85" :height="0.85"/>
          <i v-if="item.icon" class="iconfont" :class="item.icon"></i>
          <div v-else class="bg-e-i hei100"></div>
        </div>
        <h3 :class="{'col-t':item.active}">{{item.name}}</h3>
      </li>
    </ul>
  </div>
</div>
           

export default {

props: {
  config: {
    type: Object,
    default: Object
  },
  deliver: {
    type: Boolean,
    default: false,
  },
},
data () {
  return {
    width: 0,
    len: 0,
    key: 0,
    touchData: {
      index: 0,
    },
  }
},
methods: {
  getBtsGroup (bts) {
    let group = [],
      itemGroup = []
    bts.forEach((item, i) => {
      if (i % 10) {
        itemGroup.push(item)
      } else {
        itemGroup = []
        itemGroup.push(item)
        group.push(itemGroup)
      }
    })
    return group
  },
  handle (item) {
    console.log(item)
  }
},
created () {
  const that = this
  that.len = that.getBtsGroup(that.config.buttons).length
  that.len > 1 && setTimeout(() => {
    const ddBanner = that.$refs.ddBanner
    that.width = that.len * that.$refs.ddBanner.clientWidth
    ddBanner.style.width = that.width + 'px'
    this.touch({
      dom: ddBanner,
      start ({x, y, time}) {
        that.touchData.x = x
        that.touchData.y = y
        that.touchData.time = time
        let tf = ddBanner.style.transform
        that.touchData.tf = Number(tf.split('(')[1].split('px')[0])
      },
      move ({x, y}) {
        that.touchData.ex = x
        that.touchData.ey = y
        ddBanner.style.transitionDuration = '0ms'
        ddBanner.style.transform = `translateX(${that.touchData.ex - that.touchData.x + that.touchData.tf}px)`
      },
      change ({direction}) {
        switch (direction) {
          case 'left':
            that.touchData.index > -(that.len - 1) && that.touchData.index--
            break
          case 'right':
            Math.abs(that.touchData.index) > 0 && that.touchData.index++
            break
          case 'up':
            break
          case 'down':
            break
          case 'origin':
            break
        }
        that.key = Math.abs(that.touchData.index)
        ddBanner.style.transitionDuration = `500ms`
        ddBanner.style.transform = `translateX(${ddBanner.parentNode.clientWidth * that.touchData.index}px)`
      }
    })
  }, 10)
}           

}

.fon-b {

font-size: 28px;

.pad-t {

padding-top: 30px;

.pad-b-10 {

padding-bottom: 10px;

.over-h {

overflow: hidden;

.flex-wrap {

flex-wrap: wrap;

.flex {

display: flex;

.w-750 {

width: 750px;

.w20 {

width: 20%;

.t-c {

text-align: center;

.mar-a {

margin: 0 auto;

.mar-b-10 {

margin-bottom: 10px;

.bg-e-i {

background-color: #eee !important;

該元件的使用方法

export default{

data(){
    return {
         buttonGroupConfig: {
              buttons: [
                {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }, {
                  src: 'https://img.52z.com/upload/news/image/20180823/20180823122912_66977.jpg',
                  name: '女生'
                }
              ],
            },
    }
}           

由于不知道怎麼上傳螢幕錄制并生成GIF圖。具體的效果沒能展示。

作者:戴向天

來源:CSDN

原文:

https://blog.csdn.net/weixin_41088946/article/details/90764437

版權聲明:本文為部落客原創文章,轉載請附上博文連結!