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

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

QQ:809002582

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

/** 給元素綁定事件 */
      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組件其實就是一個圖片自適應的組件。 該組件內類容在上篇文章有過描述

<template>
  <div class="dd-button-group bg-f fon-b pad-t pad-b-10 over-h" :class="config.parentClass"
       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>

  </div>
</template>

<script>
  import DdImg from './dd-img'

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

</script>
<style>
.bg-f {
  background-color: #fff;
}

.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;
}
.pad-b-10 {
  padding-bottom: 10px;
}
.mar-a {
  margin: 0 auto;
}
.mar-b-10 {
  margin-bottom: 10px;
}
.bg-e-i {
  background-color: #eee !important;
}
</style>

該組件的使用方法

<dd-button-group :config="buttonGroupConfig"/>

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圖。具體的效果沒能展示。

下面這張圖片就是該組件的效果圖。

注:圖片裏面的小圓點的組件我沒有寫在代碼裏面
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章