純js實現移動端滑動控件,以上下滑動自取中間位置年齡為例;


<!-- 
    需求:上下滑動,在一個大的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 {
            width: 200px;
            height: 150px;
            background: red;
            position: fixed;
            left: 34%;
            top:0px;
            overflow:hidden;
        }
        .box{
            width:100%;
            height:100%;
        }
        .age-item{
            width: 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節點目標。 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM