移动端左右滑动切换页面效果完整代码(纯JavaScript)

作者:像素猫时间:2026-10-31 19:56:00浏览:508

本文详细介绍如何在移动端使用纯JavaScript实现左右滑动切换页面的效果。通过监听touchStart、touchMove和touchEnd三个触摸事件,计算滑动距离并判断方向,实现平滑的页面切换与回弹效果。同时结合Tab切换卡,实现滑动与高亮状态的同步,并提供完整的代码示例与性能优化建议。

一、介绍左右滑动的重要性

在移动端应用中,左右滑动交互是一种常见且重要的用户界面交互方式。它能够为用户提供流畅的操作体验,并显著增强应用的直观性和易用性。以下是实现移动端左右滑动效果的常见场景及方法概述:

  • 页面切换:在移动应用开发中,左右滑动常被用于在不同页面或视图之间进行切换。这种交互模式广泛应用于图像画廊、故事展示或导航菜单等场景,提升浏览效率。

  • 列表滑动:对于包含大量数据的长列表,用户可以通过左右滑动来浏览不同的列表项。这种滑动机制能够有效提高用户在处理海量数据时的操作效率。

  • 卡片式布局:在采用卡片式设计的界面中,左右滑动帮助用户在不同信息卡片之间进行切换,每张卡片通常代表一个独立的功能模块或信息块。

  • 弹出菜单:移动端的弹出菜单或侧边栏可以通过左右滑动操作来显示或隐藏,从而为用户提供更多的操作选项或附加信息。

  • 过渡动画:在Vue框架中,可以利用transition组件来实现左右滑动的过渡动画效果。具体做法是监听用户的触摸事件以捕捉滑动动作,并结合CSS过渡动画实现平滑的页面切换视觉效果。

  • 滑动库:若需快速实现滑动效果且对定制化要求不高,可考虑引入第三方滑动库,如Swiper或Hammer.js等。这些库提供了丰富的API接口,能带来更稳定且一致的交互体验。

  • 自定义滑动动画:开发者可根据具体业务需求,使用CSS样式与JavaScript逻辑来实现自定义的滑动动画。这包括定义动画样式、监听触摸事件以及处理复杂的滑动逻辑。

  • 性能优化:在实际项目落地时,必须考虑性能优化问题。例如,使用keep-alive来缓存页面组件,减少重复渲染开销;同时采用防抖或节流技术,避免频繁触发事件导致性能瓶颈。

通过上述多种方法,开发者可以在移动端应用中成功实现左右滑动效果,从而显著提升用户的交互体验与应用质量。

二、实现的思路

第一步:事件监听

在移动端实现滑动效果,核心在于监听三个关键的触摸事件:

  • touchStart:当用户手指接触屏幕时触发该事件。
  • touchMove:当用户手指在屏幕上移动时触发该事件。
  • touchEnd:当用户手指离开屏幕,结束触摸操作时触发该事件。

第二步:事件处理逻辑

接下来,我们需要明确在每个事件触发时应执行的具体操作:

  • touchStart 事件处理:

    • 记录触摸开始时的坐标位置(startX)。
    • 初始化滑动距离(distanceX)为0。
    • 重置滑动容器的初始位置状态。
    • 设置一个布尔标志(isMove)用于跟踪是否已开始滑动操作。
    • 代码:
              //按下
              function handleTouchStart(e) {
                  startX = e.touches[0].clientX;
                  console.log(startX); //当前按下的位置
              }
  • touchMove 事件处理:

    • 获取当前触摸点的实时坐标(currentX)。
    • 计算滑动距离(distanceX),即当前坐标与起始坐标的差值。
    • 根据计算出的滑动距离更新滑动容器的位置。
    • 判断滑动方向,若超出边界则限制滑动范围,防止越界。
    • 如果滑动距离超过预设阈值,可设置标志以触发页面切换逻辑。
    • 代码:
       //按下移动
              function handleTouchMove(e) {
                  const moveX = e.touches[0].clientX;
                  // console.log(moveX);
                  const movedDistance = Math.abs(moveX - startX); // 计算移动的距离
                  console.log(movedDistance);
                  
                  // 如果移动的距离小于80,不进行更新位置的操作
                  if (movedDistance < 80) {
                      return;
                  }
      
                  //如果 moveX 大于 startX 就是往右滑动 并且页数为0 就不行 ,或者 moveX 小于 startX 并且页数是最后一页页不行
                  if ((moveX > startX && pageIndex === 0) ||
                      (moveX < startX && pageIndex === oSliderItems.length - 1)) {
                      return
                  }
                  distanceX = moveX - startX;
                  setTranslateX(-pageWith * pageIndex + distanceX)
                  isMove = true;
              }
  • touchEnd 事件处理:

    • 判断滑动距离是否超过页面切换的阈值标准。
    • 若超过阈值,执行页面切换逻辑,跳转到目标页面。
    • 若未超过阈值,执行回弹逻辑,将滑动容器平滑恢复到初始位置。
    • 重置所有与滑动相关的变量,为下一次滑动操作做好准备。
    • //松开
              function handleTouchEnd() {
                  if (isMove) {
                      if (Math.abs(distanceX) >= pageWith / 3) {
                          if (distanceX > 0) {
                              pageIndex--;
                          }
                          if (distanceX < 0) {
                              pageIndex++;
                          }
                      }
                      setTranslateX(- pageIndex * pageWith)
                  }
      
                  startX = 0;
                  distanceX = 0;
                  isMove = false
              }
      
              function setTranslateX(tranX) {
                  oScrollWrapper.style.transition = 'all .1s'
                  oScrollWrapper.style.transform = `translate(${tranX}px)`
              }

注意:在事件中,需要判断往右或往左滑动的距离是否大于50-80像素。这样可以避免在页面很长时,用户向下滚动导致左右抖动,从而影响用户体验。

-----全部代码-以及效果展示 (JavaScript)

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>demo</title>
    <script>
        document.documentElement.style.fontSize =
            document.documentElement.clientWidth / 37.5 + 'px'
    </script>
    <style>
        body {
            margin: 0;
        }

        html,
        body,
        #app {
            height: 100%;
        }

        div {
            display: flex;
            width: 100%;
            flex-direction: column;
        }

        .slider-page {
            position: relative;
            height: 100%;
            overflow: hidden;
        }

        .scroll-wrapper {
            position: absolute;
            width: 400vw;
            height: 100%;
            flex-direction: row;
        }

        .slider-item {
            width: 100vw;
            height: 100%;
            flex: 1;
        }

        .slider-item:nth-child(1) {
            background-color: rgb(247, 150, 150);
        }

        .slider-item:nth-child(2) {
            background-color: rgb(123, 255, 0);
        }

        .slider-item:nth-child(3) {
            background-color: rgb(0, 255, 238);
        }

        .slider-item:nth-child(4) {
            background-color: rgb(255, 0, 195);
        }

        .slider-item .inner {
            height: 100%;
            justify-content: center;
            align-items: center;
            font-size: 50px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="slider-page">
            <div class="scroll-wrapper">
                <div class="slider-item">
                    <div class="inner">Page1</div>
                </div>
                <div class="slider-item">
                    <div class="inner">Page2</div>
                </div>
                <div class="slider-item">
                    <div class="inner">Page3</div>
                </div>
                <div class="slider-item">
                    <div class="inner">Page4</div>
                </div>
            </div>
        </div>
    </div>

    <script>
        //oSlidePage 最大的页面盒子
        //oScrollWrapper内部的盒子总宽
        // oSliderItems 每个小盒子
        // pageWith 页面宽度
        const oSlidePage = document.querySelector('.slider-page'),
            oScrollWrapper = oSlidePage.querySelector('.scroll-wrapper'),
            oSliderItems = oScrollWrapper.querySelectorAll('.slider-item'),
            pageWith = oSlidePage.offsetWidth;
        console.log('当前视口的宽度', pageWith);

        // 移动端事件  touchstart  touchmove touchend
        let startX = 0,
            pageIndex = 0,
            distanceX = 0
        isMove = false;

        //初始化
        const init = () => {
            bindEvent()
        }

        function bindEvent() {
            oScrollWrapper.addEventListener('touchstart', handleTouchStart, false)
            oScrollWrapper.addEventListener('touchmove', handleTouchMove, false)
            oScrollWrapper.addEventListener('touchend', handleTouchEnd, false)
        }
        //按下
        function handleTouchStart(e) {
            startX = e.touches[0].clientX;
            console.log(startX);

        }
        //按下移动
        function handleTouchMove(e) {
            const moveX = e.touches[0].clientX;
            // console.log(moveX);
            const movedDistance = Math.abs(moveX - startX); // 计算移动的距离
            console.log(movedDistance);
            
            // 如果移动的距离小于80,不进行更新位置的操作
            if (movedDistance < 80) {
                return;
            }

            //如果 moveX 大于 startX 就是往右滑动 并且页数为0 就不行 ,或者 moveX 小于 startX 并且页数是最后一页页不行
            if ((moveX > startX && pageIndex === 0) ||
                (moveX < startX && pageIndex === oSliderItems.length - 1)) {
                return
            }
            distanceX = moveX - startX;
            setTranslateX(-pageWith * pageIndex + distanceX)
            isMove = true;
        }
        //松开
        function handleTouchEnd() {
            if (isMove) {
                if (Math.abs(distanceX) >= pageWith / 3) {
                    if (distanceX > 0) {
                        pageIndex--;
                    }
                    if (distanceX < 0) {
                        pageIndex++;
                    }
                }
                setTranslateX(- pageIndex * pageWith)
            }

            startX = 0;
            distanceX = 0;
            isMove = false
        }

        function setTranslateX(tranX) {
            oScrollWrapper.style.transition = 'all .1s'
            oScrollWrapper.style.transform = `translate(${tranX}px)`
        }

        init()
    </script>
</body>

</html>

一、介绍左右滑动的重要性

扩展:实现滑动效果并结合tab切换卡,实现思路如下:

1. 设计布局

首先,设计你的tab切换卡的布局结构。这通常包括一个顶部的tab栏和下方的内容区域。每个tab对应内容区域中的一个独立页面。

2. 使用变量控制高亮

使用一个变量(如pageIndex)来跟踪当前激活的tab状态。该变量将用于控制tab栏中哪个tab项处于高亮显示状态。

3. 实现滑动逻辑

在滑动逻辑中,除了更新滑动容器的位置外,还需要根据滑动的距离来更新pageIndex的状态。当用户滑动到新页面时,相应的tab项应当被高亮显示。

4. 监听滑动事件

在touchMove和touchEnd事件中,根据滑动的距离来更新pageIndex的值,并相应地更新tab栏的高亮状态,保持界面同步。

总结

到此这篇关于移动端左右滑动切换页面效果的文章就介绍到这了,更多相关js移动端左右滑动切换内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

作者最新文章