Solve the conflict of sliding events on the mobile terminal [There are left and right sliding carousel pictures, and there are sliding scroll bars up and down, which will affect each other when tilting]

Preface

On the mobile terminal, when our page slides both up and down and left and right, for example, we have a carousel at the top (left and right), and the page also contains a scroll bar that moves up and down. When we slide the page diagonally, the page will also move diagonally, that is, the left and right movement events are triggered and the up and down movement events are triggered. The layout may also be messy, this is not what we want, we just want it to slide left and right or up and down, not at the same time. Next we will solve this problem

One, touch touch event introduction

  • touchstart: Triggered when a finger touches the screen, even if there is already a finger on the screen
  • touchmove: Triggered continuously when the finger slides on the screen. During this event, call the preventDefault() event to prevent the default event
  • touchend: triggered when the finger leaves the screen
  • touchcancel: Triggered when the system stops tracking touches. Regarding the exact departure time of this event, the document does not specify it, we can only guess

Second, the TouchEvent object

Each touch event triggers will generate a TouchEvent object, the following are the three more commonly used important attributes of TouchEvent object

  • touches: a list of all fingers currently on the screen
  • targetTouches: the list of fingers located on the current DOM element
  • changedTouches: a list of fingers involved in the current event
 wrap.addEventListener("touchstart", (e) => {
    console.log(e)
 })

Three, touchEvent object properties

Each Touch object contains the following properties

  • clientX: the x coordinate of the touch target in the viewport
  • clientY: the y coordinate of the touch target in the viewport
  • identifier: the unique ID that identifies the touch
  • pageX: the x coordinate of the touch target on the page
  • pageY: the y coordinate of the touch target on the page
  • screenX: the x coordinate of the touch target on the screen
  • screenY: the y coordinate of the touch target on the screen
  • target: the DOM node target that hits the target

Four, js solves the problem of sliding on the mobile terminal (slide case)

Solution idea: monitor the sliding, predict whether the user is sliding left or right, or up and down, if the horizontal movement distance> vertical movement distance is to do horizontal sliding, otherwise it is vertical sliding, and then solve the sliding problem by preventing default events

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    html {
      font-size: 10vw;
    }

    body {
      margin: 0;
    }

    ul {
      margin: 0;
      padding: 0;
      list-style: none;
    }

    #wrap {
      position: relative;
      width: 100vw;
      overflow: hidden;
    }

    #list {
      float: left;
      display: flex;
      display: -webkit-box;
    }

    #list li {
      flex: none;
      width: 100vw;
    }

    #list img {
      width: 100%;
      height: 200px;
      display: block;
    }

    .nav {
      position: absolute;
      left: 0;
      bottom: .2rem;
      width: 100%;
      text-align: center;
      vertical-align: top;
    }

    .nav a {
      display: inline-block;
      width: .3rem;
      height: .3rem;
      background: #fff;
      margin: 0 .1rem;
      border-radius: .15rem;
      transition: .3s;
    }

    .nav .active {
      width: .6rem;
      color: #fff;
    }

    .textList {
      margin: 0;
      padding: 0;
      list-style: none;
    }

    .textList li {
      font: 14px/40px "宋体";
      padding-left: 20px;
      border-bottom: 1px solid #000;
    }
  </style>
</head>

<body>
  <div id="wrap">

    <!-- 幻灯片 -->
    <ul id="list">
      <li><img src="https://i02piccdn.sogoucdn.com/f8773bf41fc728d8" alt=""></li>
      <li><img src="https://i02piccdn.sogoucdn.com/03469eff264233a8" alt=""></li>
      <li><img src="https://i02piccdn.sogoucdn.com/b8322a9d8751fd62" alt=""></li>
      <li><img src="https://i04piccdn.sogoucdn.com/87a97031f6954b64" alt=""></li>
      <li><img src="https://i03piccdn.sogoucdn.com/d1eef212d4b16e56" alt=""></li>
    </ul>

    <!-- 点 -->
    <nav class="nav">
      <a class="active"></a>
      <a></a>
      <a></a>
      <a></a>
      <a></a>
    </nav>

  </div>

  <!-- 测试数据列表 -->
  <ul class="textList"></ul>

  <script>
    // 生成两百行测试数据列表
    {
      let list = document.querySelector(".textList");
      list.innerHTML = [...(".".repeat(200))].map((item, index) => {
        return `<li>这是第${index}行测试数据</li>`;
      }).join("");
    }


    // 幻灯片 
    /*
        在两个方向的滑动上,如果有一些不同的操作,这里要注意我们要进行方向判断
        每次滑动时判断方向,一旦判明方向,就不在判断
    */
    {
      let wrap = document.querySelector("#wrap");
      let list = document.querySelector("#list");
      let navs = document.querySelectorAll(".nav a");
      let startPoint = {}; 
      let translateX = 0;
      let startTranslateX = 0;
      let now = 0;
      let wrapW = wrap.clientWidth;
      const range = .3 * wrapW;
      let isFirst = true;
      let isMove = true;
      list.innerHTML += list.innerHTML;

      // 当手指触摸屏幕时触发
      wrap.addEventListener("touchstart", (e) => {
        let touch = e.changedTouches[0];
        list.style.transition = "none";
        startPoint = {
          x: touch.pageX,
          y: touch.pageY
        };
        if (now == 0) {
          now = navs.length;
        } else if (now == navs.length * 2 - 1) {
          now = navs.length - 1;
        }
        translateX = -now * wrapW;
        list.style.transform = `translateX(${translateX}px)`;
        startTranslateX = translateX;
        isFirst = true;
        isMove = true;
      });
      
      // 当手指在屏幕上滑动时连续地触发
      wrap.addEventListener("touchmove", (e) => {
        let touch = e.changedTouches[0];
        let nowPoint = {
          x: touch.pageX,
          y: touch.pageY
        };
        let dis = {
          x: nowPoint.x - startPoint.x,
          y: nowPoint.y - startPoint.y
        };
        // 在安卓下,手指按下时,如果触摸面积比较大,容易误触 touchmove
        if (isFirst) {
          if (Math.abs(dis.x) - Math.abs(dis.y) > 5) {
            // 左右滑动, 阻止滚动条不进行上下滑动,而让幻灯片滑动
            isMove = true;
            isFirst = false;
          } else if (Math.abs(dis.y) - Math.abs(dis.x) > 5) {
            // 上下滑动, 不阻止滚动条滑动,禁止幻灯片滑动
            isMove = false;
            isFirst = false;
          }
        }
        if (isMove) {
          e.preventDefault();
          if (!isFirst) {
            translateX = startTranslateX + dis.x;
            list.style.transform = `translateX(${translateX}px)`;
          }
        }
      });
      
      // 当手指从屏幕上离开时触发
      wrap.addEventListener("touchend", (e) => {
        let touch = e.changedTouches[0];
        let nowPoint = {
          x: touch.pageX,
          y: touch.pageY
        };
        let dis = {
          x: nowPoint.x - startPoint.x,
          y: nowPoint.y - startPoint.y
        };
        
        if (Math.abs(dis.x) > range && isMove) {
          now -= dis.x / Math.abs(dis.x);
        }

        navs.forEach(item => {
          item.classList.remove("active")
        });
        translateX = -now * wrapW;
        list.style.transition = ".3s";
        list.style.transform = `translateX(${translateX}px)`;
        navs[now % navs.length].classList.add("active");
      });
    }    
  </script>
</body>

</html>

Five, renderings

Six, mobile scrolling plug-in

Swiper: https://github.com/nolimits4web/Swiper

better-scroll: https://ustbhuangyi.github.io/better-scroll/#/zh

 

Articles are continuously updated every week. You can search for " Front-end Collection  " on WeChat to  read it for the first time, and reply to [ Video ] [ Book ] to receive 200G video materials and 30 PDF book materials

Guess you like

Origin blog.csdn.net/qq_38128179/article/details/114287812