前端JS H5 touch事件封装,更加高效的开发移动端 - 戴向天

33 篇文章 0 订阅
14 篇文章 0 订阅

大家好!我叫戴向天。今天我给大家分享一个我自己封装的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图。具体的效果没能展示。

下面这张图片就是该组件的效果图。

注:图片里面的小圆点的组件我没有写在代码里面
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值