<!-- 需求:上下滑动,在一个大的div块里显示5个小的值,滑动过程中自动获取中间位置的值 需要注意的是: 1 touchmove会多次被触发; 2 获取中间位置的值可以通过定位得top值来获取 3 以1到99为例,上下滑动时一定注意若取中间值,首尾一定需要切值滑动到中间位置; 当页面显示为 93 94 95 96 97时,在向上滑动时 ,假设在滑动divHeight*5的距离, 这样最后页面显示将只存在98 99 ,取中间值时将为空; 同样显示为 3,4,5,6,7时,在向下滑动滑动时 ,假设在滑动divHeight*5的距离, 这样最后页面显示将只存在98 99 ,取中间值时将为空; 但是需要注意的是最小值和最大值必须在中间位置出现 --> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="format-detection" content="telephone=no, email=no" /> <title>Document</title> <style> #id { 200px; height: 150px; background: red; position: fixed; left: 34%; top:0px; overflow:hidden; } .box{ 100%; height:100%; } .age-item{ 30px; height: 30px; background: green; border: solid 1px grey; position:absolute; /*top:0;*/ } .box .age-option-select{ font-size: 16px; color: #ffffff; background-color: #0000ff; } </style> <script> function cons(idx){ console.log(idx) } function load() { /*单指拖动*/ var itemHeight = 30; //每个item选项的高度 var obj = document.querySelector('.box'); var html2 = ''; for(var i=1;i<100;i++){ html2+='<div class="age-item" onclick="cons('+i+')" style="top:'+(i-1)*itemHeight+'px">'+i+'</div>' } obj.innerHTML = html2; var touchStart = 0; var touchEnd =0; var ageOption = document.getElementsByClassName('age-item'); changeSelectStyle(ageOption); obj.addEventListener("touchstart", function(event) { var touch = event.targetTouches[0]; touchStart = touch.pageY; obj.addEventListener('touchmove', function(event) { // 如果这个元素的位置内只有一个手指的话 if (event.targetTouches.length == 1) { event.preventDefault(); // 阻止浏览器默认事件 var touch = event.targetTouches[0]; touchEnd = touch.pageY; } }, false); }); obj.addEventListener("touchend", function() { var ages = document.getElementsByClassName('age-item'); if(touchEnd-touchStart>0){ //向下滑 var ageItem = 0; for(let j=0;j<ages.length;j++){ if(ages[j].style.top == '0px'|| ages[j].style.top == 0){ ageItem = ages[j].innerHTML; break; } } if(parseInt(ages[0].style.top)>=2*itemHeight){ return; }else{ if(parseInt(ageItem)+1 < Math.ceil((touchEnd-touchStart)/itemHeight)){ var diff = parseInt(ageItem)+1; changeTop(ages,diff); }else{ var diff = Math.ceil((touchEnd-touchStart)/itemHeight); changeTop(ages,diff); } } }else{ //向上滑 var ageItem = 0; for(let k=ages.length-1;k>0;k--){ if(ages[k].style.top == 4*itemHeight +'px'){ ageItem = ages[k].innerHTML; break; } } if(parseInt(ages[ages.length-1].style.top)<=2*itemHeight){ return; }else{ if(ageItem==''){ var diff = -1; changeTop(ages,diff); }else if((99-parseInt(ageItem))+2<Math.ceil(Math.abs(touchEnd-touchStart)/itemHeight)){ var diff = parseInt(ageItem)-99-2; changeTop(ages,diff); }else{ var diff = Math.ceil((touchEnd-touchStart)/itemHeight); changeTop(ages,diff); } } } // 由于上面需要修改99次样式,需要进行99次的重绘;可以修改为重新插入一次,在此不详细列出 delEvent(obj,'touchstart'); delEvent(obj,'touchmove'); }); function delEvent(obj,evt,fn,useCapture){ if (obj.removeEventListener) { //先使用W3C的方法移除事件处理函数 obj.removeEventListener(evt,fn,!!useCapture); }else { if(obj.__EventHandles){ var fns = obj.__EventHandles[evt]; if(fns){delete fns[fn.__EventID];} } } } function changeTop(obj,diff){ for(let k=0;k<obj.length;k++){ obj[k].style.top = parseInt(obj[k].style.top) + diff*itemHeight +'px'; } changeSelectStyle(ageOption); } function changeSelectStyle(arr){ for(var i=0 ; i < arr.length ; i++){ if(hasClass('age-option-select',arr[i])){ removeClass('age-option-select',arr[i]) } if(arr[i].style.top!=undefined && arr[i].style.top == 2*itemHeight+'px'){ if(!hasClass('age-option-select',arr[i])){ addClass('age-option-select',arr[i]) } } } } } // 公有方法 function hasClass(cla, element) { if(element.className.trim().length === 0) return false; var allClass = element.className.trim().split(" "); return allClass.indexOf(cla) > -1; } function addClass(cla,element){ if(!hasClass(cla,element)){ if(element.setAttribute){ element.setAttribute("class",element.getAttribute("class")+" "+cla); }else{ element.className = element.className+" "+cla; } } } function removeClass(cla,element){ if(hasClass(cla,element)){ var allClass = element.className.trim().split(" "); allClass.splice(allClass.indexOf(cla),1); element.className = allClass.join(' '); } } </script> </head> <body onload="load()"> <div id="inp"></div> <div id="id" style="top:0px;"> <div class="box" style="top:0px;"> </div> </div> </body> </html>
用户在移动端浏览H5的时候,会使用手指进行一连串的操作,单击、双击、上拉、下拉等等一系列操作,这里主要针对touch事件进行一些简单的介绍;
用户从手指触碰到屏幕到手指离开屏幕这中间,会触发一系列的touch事件:
①touchstart:当手指触碰到屏幕的时候触发
②touchmove:当手指在屏幕上滑动的时候触发
③touchend:当手指离开屏幕的时候时候触发
④touchcancel事件:当系统停止跟踪触摸的时候触发(这个事件很少会用,一般不做深入研究)。
一般来讲,从手指触碰到屏幕,到手指离开屏幕,至少会触发touchstart、touchmove、touchend三个事件,因为手指按下与抬起时候的位置,不可能完全相同(当然也会有例外);
使用:
监听这3个事件:
1. window.touchstart= function(event){}
2. window.touchmove= function(event){}
3. window.touchend= function(event){}
event:
1. touches:表示当前跟踪的触摸操作的touch对象的数组。
2. targetTouches:特定于事件目标的Touch对象的数组。
3. changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组。
每个touch对象包含的属性
1. clientX:触摸目标在视口中的x坐标。
2. clientY:触摸目标在视口中的y坐标。
3. identifier:标识触摸的唯一ID。
4. pageX:触摸目标在页面中的x坐标。
5. pageY:触摸目标在页面中的y坐标。
6. screenX:触摸目标在屏幕中的x坐标。
7. screenY:触摸目标在屏幕中的y坐标。
8. target:触目的DOM节点目标。