移动端touch事件实现无缝滚动及下拉刷新
2018-08-09 本文已影响0人
samfung09
pc端的鼠标事件写多了,但移动端没有鼠标,所以来写写移动端的touch事件。touch事件主要用到touchstart,touchmove,touchend三个事件,事件没什么好说的,做效果是最主要用到的是touch事件对象给我们提供的几个属性
touches 屏幕触点集合
targetTouches touch事件绑定元素身上的触点集合
changesTouches 发生改变了的触点集合
以下引用segmentfault@pangpang的图:
895887-20161012094941109-1469533517.png手势
说到手势,那么可以确定当前至少有两个以上触点,下面就来简单的说说两个触点的旋转手势和缩放手势。其实很简单,在touchstart事件中确定两个触点(e.targetTouches[0],e.targetTouches[1])
的初始坐标,然后在touchmove事件中得到移动后的两触点坐标,然后进行计算判断,下面是我画的计算图
无缝滚动
pc端的无缝轮播写了很多次了,其实移动端的无缝滚动原理也差不多。这世界没有真正的无缝滚动,都是些障眼法,在pc端要将第一个滑块复制一份加到最后,而移动端要将原来第一和最后一个滑块复制出来分别加到最后面和最前面。举例原来有四个滑块排列1、2、3、4,现在将它变成4、1、2、3、4、1共六块,如果当前touch事件target元素为第一个4时,则将当前可视区平移到第二个4,如果当前touch事件target元素为最后一个1时,则将当前可视区平移到第一个1。
具体实现看代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>touch无缝滚动</title>
<style>
*{
margin: 0;
padding: 0;
}
html, body{
width: 100%;
height: 100%;
}
html{
font-size: 20px;
}
#banner{
width: 100%;
height: 8rem;
}
#banner ul{
width: 75rem;
overflow: hidden;
list-style: none;
}
#banner ul li{
width: 18.75rem;
height: 8rem;
float: left;
color: white;
font-size: 26px;
line-height: 8rem;
text-align: center;
}
</style>
</head>
<body>
<div id="banner">
<ul>
<li style="background: pink">1</li>
<li style="background: orange">2</li>
<li style="background: purple">3</li>
<li style="background: skyblue">4</li>
</ul>
</div>
<script>
//移动端rem兼容
document.documentElement.style.fontSize = 20*document.documentElement.clientWidth/375 + 'px';
var banner = document.getElementById('banner');
var ul = banner.getElementsByTagName('ul')[0];
var w = ul.firstElementChild.offsetWidth;
var i = 1;
//在ul首尾添加li,为了无缝滚动
ul.insertBefore(ul.lastElementChild.cloneNode(true), ul.children[0]);
ul.appendChild(ul.children[1].cloneNode(true));
ul.style.width = ul.children.length*w+'px';
//当前ul滑动到什么位置了
var bannerLeft = -w * i;
ul.style.transform = 'translateX('+bannerLeft+'px)';
var startX = 0, startY = 0;
var disX = 0, dir = '';
banner.addEventListener('touchstart', function(e){
e.preventDefault()
// e.cancelBubble = true;
ul.style.transition = ''; //先清除ul上的transition
startX = e.targetTouches[0].clientX;
dir = ''; //每开始touch一次先清除滑动方向
//如果当前touch的是第一个li,则将ul平移到倒数第二个li的位置
if(e.target == ul.firstElementChild){
i = ul.children.length-2;
bannerLeft = -w * i;
ul.style.transform = 'translateX('+bannerLeft+'px)';
//如果当前touch的是最后一个li,则将ul平移到第二个li的位置
}else if(e.target == ul.lastElementChild){
i = 1;
bannerLeft = -w * i;
ul.style.transform = 'translateX('+bannerLeft+'px)';
}
disX = startX - bannerLeft;
banner.addEventListener('touchmove', function(e){
e.preventDefault()
//如果滑动方向还没确定,先确定一下
if(!dir){
if(Math.abs(e.targetTouches[0].clientX - startX) > 5){//如果先横向滑动了5px
dir = 'x';
}
}else{
if(dir == 'x'){ //如果当前是横向滑动
bannerLeft = e.targetTouches[0].clientX - disX;
ul.style.transform = 'translateX('+bannerLeft+'px)';
}
}
}, false);
banner.addEventListener('touchend', function(){
//当前松手位置与屏幕垂直中线比较,判断松手后滑块回弹到哪里
i = Math.round(-bannerLeft/w);
bannerLeft = -w *i;
ul.style.transition = '0.3s'; //回弹时加上过度效果
ul.style.transform = 'translateX('+bannerLeft+'px)';
}, false);
}, false);
</script>
</body>
</html>
效果
GIF.gif