触屏事件
touch对象对表一个触摸点,常见的触屏事件如下:
触屏事件对象
TouchEvent是一类描述手指在触摸平面上的状态变化的事件。以上三个触屏事件都是事件对象。其中常见的三个对象列表如下:
div.addEventListener('touchstart',function(e){ console.log(e.touches);//正在触摸屏幕的所有手指的列表(所有被触摸的点) })
其中changedTouches是经常使用的,因为一般都是触摸元素。
移动端拖动元素
- touchstart、touchmove、touchend可以实现拖动元素
- 但是拖动元素需要当前手指的坐标值,我们可以使用targetTouches[0]里面的pageX和pageY来获得。
- 移动端拖动原理:手指移动中计算出手指移动的距离,然后用盒子原来的位置+手指移动的距离
- 手指移动的距离:手指滑动中的位置 减去 手指刚开始触摸的位置。
手指移动也会触发滚动屏幕,所以这里要阻止默认的屏幕滚动e.preventDefault();
<script> var div = document.querySelector('div'); var startX = 0; //获取手指初始坐标 var startY = 0; var x = 0; //获得盒子原来的位置 var y = 0; div.addEventListener('touchstart', function(e) { //获取手指初始坐标 startX = e.targetTouches[0].pageX; startY = e.targetTouches[0].pageY; x = this.offsetLeft; y = this.offsetTop; }); div.addEventListener('touchmove', function(e) { //计算手指的移动距离:手指移动之后的坐标减去手指初始的坐标 var moveX = e.targetTouches[0].pageX - startX; var moveY = e.targetTouches[0].pageY - startY; //移动我们的盒子 盒子原来的位置 + 手指移动的距离 this.style.left = x + moveX + 'px'; this.style.top = y + moveY + 'px'; e.preventDefault(); //阻止屏幕滚动的默认行为 }); </script>结果演示
轮播图
classList属性(IE10+)
它可以返回元素的类名,并且它还可以用于在元素中添加、移除以及切换css类的功能。
追加类:
element.classList.add('类名'); //不会覆盖以前的类名
移除类名:
element.classList.remove('类名');
切换类名:
element.classList.toggle('类名'); //调用一次就加上,再调用一次就移除(有这个类,就去掉;没有这个类,就加上。
轮播图分析
自动播放功能
- 开启定时器
- 移动端移动可以使用translate移动
- 添加过渡效果
- 无缝滚动原理
- 等图片滚动过渡完成后再去判断图片是否滚动了最后一张。
- 判断条件:如果索引号等于3说明走到最后一张图片了,此时索引号要复原为0。
- 此时图片去掉过渡效果,然后移动
- 如果索引号小于0,说明是倒着走,索引号等于2
- 此时图片去掉过渡效果,然后移动
- 小圆点跟随变化效果
- 把ol里面li带有current类名选出来并且去掉类名
- 让当前索引号的小li加上crrent
- 注意,是等着过渡结束之后再跟随变化,所以要写到transitionend事件里面。
手指滑动轮播图
- 本质就是ul跟随手指移动,简单说就是移动端拖动元素
- 触摸元素touchstart:获取手指初始坐标
- 移动手指touchmove:计算手指的滑动距离,并且移动盒子
- 手指触摸的时候就停止定时器
- 离开手指touchennd:根据滑动的距离分不同的情况
- 如果移动距离小于某个像素,就回弹到原来的位置
- 如果移动距离大于某个像素,就自动滑动到上一张或下一张
<script> var foucus=document.querySelector('.foucus'); var ul=foucus.children[0]; var ol=foucus.children[1]; var w=foucus.offsetWidth;//获得foucus的200px宽度 var flag=false;//只有手指移动了才去计算距离,优化轮播图 // 利用定时器自动轮播图片 var index=0; var timer=setInterval(function(){ index++; var translatex = -index * w; ul.style.transition='all .3s'; //过渡效果 ul.style.transform = 'translateX('+translatex+'px)';//移动ul实现轮播 },2000); //无缝滚动 // 等图片滚动过渡完成后再去判断ul是否滚动了最后一张。 //每一张图片过渡完成都会执行一次这个事件 ul.addEventListener('transitionend',function(){ if(index>=3){ index=0; // 此时图片去掉过渡效果,然后让ul快速的跳到目标位置 ul.style.transition='none'; //利用最新的索引滚动图片 var translatex = -index * w; ul.style.transform = 'translateX(' + translatex + 'px)';//移动ul实现轮播 }else if(index < 0){ index=2; // 此时图片去掉过渡效果,然后让ul快速的跳到目标位置 ul.style.transition = 'none'; //利用最新的索引滚动图片 var translatex = -index * w; ul.style.transform = 'translateX(' + translatex + 'px)';//移动ul实现轮播 } //小圆点跟随变化 // 把ol里面li带有current类名选出来并且去掉类名 ol.querySelector('li.current').classList.remove('current'); // 让当前索引号的小li加上crrent ol.children[index].classList.add('current'); }) //手指滑动轮播图 // 触摸元素touchstart:获取手指初始坐标 var startX=0; var moveX=0; ul.addEventListener('touchstart',function(e){ startX=e.targetTouches[0].pageX; //手指触摸的时候就停止定时器 clearInterval(timer); }) // 移动手指touchmove:计算手指的滑动距离,并且移动盒子 ul.addEventListener('touchmove',function(e){ //计算手指移动距离 moveX=e.targetTouches[0].pageX - startX; //移动盒子: 盒子原来的位置+手指移动的距离 var boxX=-index * w + moveX; //手指拖动的时候,不需要动画效果,所以要取消过渡效果,然后再移动 ul.style.transition='none'; ul.style.transform = 'translateX(' + boxX + 'px)';//移动ul实现轮播 flag=true;//检测到手指已经移动 e.preventDefault(); //阻止默认屏幕滚动的行为 }) //手指离开 ul.addEventListener('touchend',function(e){ if(flag){ //如果手指移动了,才去计算距离,点击的不会去计算 // 如果移动距离大于某个像素,就自动滑动到上一张或下一张 if (Math.abs(moveX) > 50) { //如果是右滑,就播放上一张,moveX是正值 if (moveX > 0) { index--; } else { //如果是左滑,就播放下一张,moveX是负值 index++; } // 如果移动距离小于某个像素,就回弹到原来的位置 var moveHandX = -index * w; ul.style.transition = 'all .3s'; ul.style.transform = 'translateX(' + moveHandX + 'px)';//移动ul实现轮播 } else { //如果移动距离小于50像素就回弹 var moveHandX = -index * w; ul.style.transition = 'all .1s'; ul.style.transform = 'translateX(' + moveHandX + 'px)';//移动ul实现轮播 } } //手指离开后重新开启定时器 clearInterval(timer); //先清除定时器 timer = setInterval(function () { index++; var translatex = -index * w; ul.style.transition = 'all .3s'; //过渡效果 ul.style.transform = 'translateX(' + translatex + 'px)';//移动ul实现轮播 }, 2000); }) </script>结果演示
返回顶部
var goBack=document.querySelector('.goBack'); var nav=document.querySelector('nav'); window.addEventListener('scroll',function(){ if(window.pageYOffset >= nav.offsetTop){ goBack.style.display='block'; }else{ goBack.style.display='none'; } }) goBack.addEventListener('click',function(){ window.scroll(0,0); })
click延时解决方案(推荐用插件)
移动端click事件会有300ms的延时,原因是移动端会考虑用户是否双击缩放屏幕,会有一个等待
解决方案1(不推荐)
禁用缩放
<meta name="viewport" content="user-scalable=no">
解决方案2(不推荐,一次只能调用一个)
利用touch事件自己封装这个事件
- 当手指触摸屏幕的时候,记录当前事件
- 当手指离开屏幕,用离开的时间 – 触摸的时间
- 如果小于150ms,并且没有滑动过屏幕,那么就认为用户是在点击。
function clickTime(obj,callback){ var isMove=false; var startTime=0;//记录触摸时候的时间 obj.addEventListener('touchstart',function(e){ startTime=Date.now();//记录触摸时间 }); obj.addEventListener('touchmove',function(e){ isMove=true; //看看是否有滑动,有滑动算拖拽,不算点击 }); obj.addEventListener('touchend',function(e){ //如果触摸了且离开事件小于150ms就算点击 if(!isMove && (Date.now() - startTime) < 150){ callback && callback();//执行回调函数 } isMove = false; //重置 startTime=0; }) } //调用 clickTime(goBack,function(){ //执行代码 })
插件(举例)
fastclick解决延时插件
第一步:引入插件
<script src="fastclick.js"></script>
第二步:判断事件是否属于页面 (从插件文档里复制的下面代码)
if('addEventListener' in document){ document.addEventListener('DOMContentLoaded',function(){ FastClick.attach(document.body); },false); }
第三步:使用插件
var btn = document.querySelector('button'); btn.addEventListener('click',function(){ })
轮播图插件
swiper插件