底部悬浮框 上拉和下拉功能

2023-08-15 08:08:40 浏览数 (1)

实现一个通过触摸拖动操作来展开和收起底部悬浮框,并根据拖动过程中的位置和状态来调整底部容器的高度和展开状态的功能

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,viewport-fit=cover" />
        <meta name="format-detection" content="telephone=no, email=no, date=no, address=no" />
        <link href="css/history.css" rel="stylesheet">
        <link rel="stylesheet" href="css/bootstrap.min.css">
        <link rel="stylesheet" href="css/bootstrap-theme.min.css">

        <title>history</title>
        <style>
            html,
            body {
                padding: 0;
                margin: 0;
            }

        
        
            /* 固定tab样式 */
            .tab-container {
              position: fixed;
              top: 6%;
              left: 0;
              width: 100%;
              background-color: #fff;
              box-shadow: 0 2px 4px rgba(0,0,0,.1);
            }
            .tab-item {
              display: inline-block;
              padding: 10px 18px;
              cursor: pointer;
            }
            .tab-item.active {
              background-color: #f1f1f1;
              color: #333;
            }
            
    .footer-container {
      position: fixed;
      left: 0;
      bottom: 0;
      width: 100%;
      height: 45vh;
      background-color: #f2f2f2;
      box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.2);
      overflow-y: hidden;
      transition: transform 0.3s ease;
      touch-action: pan-y; /* 允许垂直方向上的拖动 */
    }
    
    .footer-container.open {
      transform: translateY(0%); /* 展开时显示在屏幕上方 */
    }
    
    .floating-box {
      max-width: 600px;
      margin: 0 auto;
      padding: 20px;
      text-align: center;
      background-color: #fff;
      cursor: grab; /* 显示拖动手势 */
    }
        </style>
    </head>
    <body>
        <!-- 判断地图的类型 -->
        <input type="text" id="imageryProvider" hidden="true">
        <!-- 公共使用的placeId -->
        <input type="text" id="placeId" hidden="true">
        <!-- 2Dim为1时代表代表矢量地图 -->
        <input type="text" id="floorNum" hidden="true">
        <!-- 2Dim为2时代表切片图 -->
        <input type="text" id="tileUrl" hidden="true">
        <input type="text" id="tileName" hidden="true">
        <!-- 公共的精度纬度的坐标,所有关于Center都取它 -->
        <input type="text" id="mapCenter" hidden="true">
        <!-- 判断2D和3D的初始化 -->
        <input type="text" id="TwoDim" hidden="true">
        <!-- 地图楼层切换参数 -->
        <input type="text" id="tilesName" hidden="true">
        <div class="col-md-8 col-sm-8" style="padding: 0;;">
            <div class="tab-container">
                <div class="tab-item active">员工</div>

                <div class="tab-item">访客</div>
                <div class="tab-item">车辆</div>
                <div class="tab-item">承包商</div>
                <div class="tab-item">工具车</div>
            </div>

            <div id="cesiumContainer_2D" style="height: 666px;">
                <div class="floorBar"></div>
            </div>


            <div class="footer-container">
                <div class="floating-box">
                    <h3>底部悬浮框</h3>
                    <p  onclick="orientation()">这是一个底部悬浮框的示例内容。</p>
                </div>
            </div>

        </div>



    </body>

    <script src="jquery-2.1.1.min.js"></script>



    <script>
    
    
    function orientation(lon, lat){
        alert(1)
    }


        var footerContainer = document.querySelector('.footer-container');
        var floatingBox = document.querySelector('.floating-box');
        var startY = 0;
        var currentY = 0;
        var isDragging = false;
        var isExpanded = false;
        var floatingBoxHeight = floatingBox.offsetHeight;
        var originalHeight = footerContainer.offsetHeight;

        floatingBox.addEventListener('touchstart', function(e) {
            startY = e.touches[0].clientY;
            currentY = startY;
            isDragging = true;

            e.preventDefault(); // 防止触发默认拖动行为
        });

        floatingBox.addEventListener('touchmove', function(e) {
            var windowHeight = window.innerHeight;
            if (!isDragging) return;

            var deltaY = e.touches[0].clientY - currentY;
            currentY = e.touches[0].clientY;

            var newHeight = Math.max(0, footerContainer.offsetHeight - deltaY);
            footerContainer.style.height = newHeight   'px';

            if (newHeight < originalHeight && isExpanded) {
                footerContainer.style.height = originalHeight   'px';
                isExpanded = false;
            }

            var distanceFromBottom = windowHeight - (floatingBox.getBoundingClientRect().top   floatingBoxHeight);
            var tabContainer = document.querySelector('.tab-container')
            var distanceFromTop = floatingBox.getBoundingClientRect().top - ((windowHeight - tabContainer.offsetTop -
                floatingBoxHeight) / 3   tabContainer.offsetTop   tabContainer.offsetHeight)
            console.log(floatingBox.getBoundingClientRect(), (windowHeight - tabContainer.offsetTop - floatingBoxHeight) / 3, {
                distanceFromTop,
                floatingBoxHeight,
                originalHeight,
                windowHeight: window.innerHeight,
                distanceFromBottom,
                originalHeight
            })
            if (distanceFromBottom <= 0) {
                isExpanded = false;
                isDragging = false;
                footerContainer.style.height = floatingBoxHeight   'px'
            }
            if (distanceFromTop <= 0) {
                isExpanded = false;
                isDragging = false;
                footerContainer.style.height = windowHeight - ((windowHeight - tabContainer.offsetTop - floatingBoxHeight) / 3  
                    tabContainer.offsetTop   tabContainer.offsetHeight)   'px'
            }
        });

        floatingBox.addEventListener('touchend', function() {
            isDragging = false;

            if (footerContainer.offsetHeight > originalHeight && !isExpanded) {
                footerContainer.classList.add('open');
                isExpanded = true;
            } else if (footerContainer.offsetHeight <= originalHeight && isExpanded) {
                footerContainer.classList.remove('open');
                isExpanded = false;
            }
        });
    </script>
</html>

这段代码实现了一个具有拖动效果的底部悬浮框。

1:通过document.querySelector()方法选择.footer-container类和.floating-box类的元素,并将它们分别赋值给footerContainer和floatingBox变量。

2:定义了一些变量用于记录拖动过程中的状态和位置,包括startY(起始Y坐标)、currentY(当前Y坐标)、isDragging(是否正在拖动)、isExpanded(悬浮框是否展开)、floatingBoxHeight(悬浮框的高度)和originalHeight(底部容器的初始高度)。

3:添加touchstart事件监听器,当触摸开始时,记录起始Y坐标、当前Y坐标,并将isDragging标志设置为true。同时,通过e.preventDefault()阻止默认的拖动行为。

4:添加touchmove事件监听器,当触摸移动时,根据手指的移动距离计算新的高度,并将底部容器的高度设置为新的高度。如果底部容器的高度小于初始高度且悬浮框已展开,则将底部容器的高度设置为初始高度,同时将isExpanded标志设置为false。

5:悬浮框与窗口底部的距离和悬浮框与页面顶部的距离,判断是否需要展开或收起底部容器。如果悬浮框与窗口底部的距离小于等于0,则将底部容器的高度设置为悬浮框的高度,并将isExpanded和isDragging标志设置为false。如果悬浮框与页面顶部的距离小于等于0,则将底部容器的高度设置为窗口高度减去悬浮框与顶部容器之间的距离,并将isExpanded和isDragging标志设置为false。

6:添加了touchend事件监听器,当触摸结束时,将isDragging标志设置为false。根据底部容器的高度和展开状态,添加或移除.open类,以控制底部容器的展开和收起。

0 人点赞