当前位置: 首页 > 知识库问答 >
问题:

javascript - js如何控制移动端overflow:scroll容器滑动的最大速度?

翟高明
2025-01-10
<div class="box">
    <div class="main">
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <div>4</div>
        <div>5</div>
    </div>
</div>
.box {
  width: 400px;
  height: 60px;
  border: 2px solid blue;
  overflow: auto;
}
.main {
  width: 1000px;
  height: 100%;
  background: yellow;
  display: flex;
  align-items: center
}
.main div {
    flex: 1;
    text-align: center;
}

demo在这:https://jsrun.net/gBtKp
在移动端滑动一下这个.box区域,稍微一用力就到头了,如果我想用js去控制他滑动的最大速度该怎么去处理?

共有5个答案

笪健
2025-01-10

可以通过 touchmove 事件监听来控制滑动速度,结合 event.preventDefault() 和自定义逻辑实现滑动速率限制:

let lastTouchY = 0;
let velocity = 0;
const maxVelocity = 2; // 最大速度

document.querySelector('.scroll-container').addEventListener('touchmove', (event) => {
  const currentTouchY = event.touches[0].clientY;
  const deltaY = currentTouchY - lastTouchY;

  velocity = Math.abs(deltaY);
  if (velocity > maxVelocity) {
    event.preventDefault(); // 阻止默认滑动行为
    return;
  }

  lastTouchY = currentTouchY;
});

注意:这种实现方式会影响用户体验,建议谨慎使用。

吕皓
2025-01-10
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scroll Speed Control</title>
    <style>
        .box {
            width: 400px;
            height: 60px;
            border: 2px solid blue;
            overflow: auto;
        }
        .main {
            width: 1000px;
            height: 100%;
            background: yellow;
            display: flex;
            align-items: center;
        }
        .main div {
            flex: 1;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="main">
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <div>4</div>
            <div>5</div>
        </div>
    </div>
    <script>
        const container = document.querySelector('.box');
        let startY = 0;
        let startScrollTop = 0;
        let lastTimestamp = 0;
        const maxSpeed = 0.5; // 最大速度,单位:像素/毫秒

        container.addEventListener('touchstart', (event) => {
            startY = event.touches[0].clientY;
            startScrollTop = container.scrollTop;
            lastTimestamp = event.timeStamp;
        });

        container.addEventListener('touchmove', (event) => {
            const currentY = event.touches[0].clientY;
            const currentTimestamp = event.timeStamp;
            const deltaY = startY - currentY;
            const deltaTime = currentTimestamp - lastTimestamp;

            if (deltaTime > 0) {
                const speed = deltaY / deltaTime;
                if (Math.abs(speed) > maxSpeed) {
                    event.preventDefault();
                    container.scrollTop = startScrollTop + Math.sign(deltaY) * maxSpeed * deltaTime;
                } else {
                    container.scrollTop = startScrollTop + deltaY;
                }
            }
        });

        container.addEventListener('touchend', () => {
            startY = 0;
            startScrollTop = 0;
            lastTimestamp = 0;
        });
    </script>
</body>
</html>

邢曦
2025-01-10

1736407840845.png

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        .box {
            width: 400px;
            height: 60px;
            border: 2px solid blue;
            overflow: hidden; 
            position: relative;
        }
        .main {
            width: 1000px;
            height: 100%;
            background: yellow;
            display: flex;
            align-items: center;
            position: absolute; 
            left: 0;
            top: 0;
            transform: translateX(0);
            transition: transform 0.3s; 
        }
        .main div {
            flex: 1;
            text-align: center;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="main">
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <div>4</div>
            <div>5</div>
        </div>
    </div>

    <script>
        const box = document.querySelector('.box');
        const main = document.querySelector('.main');
        let startX = 0;
        let scrollLeft = 0;
        let isDragging = false;
        let lastX = 0;
        let velocity = 0;
        let maxVelocity = 15; // 控制最大滑动速度
        let animationId;

        function handleTouchStart(e) {
            isDragging = true;
            startX = e.touches[0].pageX - main.offsetLeft;
            lastX = e.touches[0].pageX;
            
            cancelAnimationFrame(animationId);
            
            main.style.transition = 'none';
        }

        function handleTouchMove(e) {
            if (!isDragging) return;

            e.preventDefault();
            const currentX = e.touches[0].pageX;
            const diff = currentX - lastX;
            
            // 计算速度
            velocity = Math.min(Math.abs(diff), maxVelocity) * Math.sign(diff);
            
            // 计算新位置
            const newLeft = parseInt(main.style.transform.replace('translateX(', '')) || 0;
            const nextPos = newLeft + velocity;
            
            // 限制边界
            const maxScroll = box.offsetWidth - main.offsetWidth;
            const boundedPos = Math.max(maxScroll, Math.min(0, nextPos));
            
            // 应用位移
            main.style.transform = `translateX(${boundedPos}px)`;
            
            lastX = currentX;
        }

        function handleTouchEnd(e) {
            isDragging = false;
            
            // 加惯性滑动
            const decelerate = () => {
                if (Math.abs(velocity) > 0.5) {
                    velocity *= 0.95; // 减速因子
                    
                    const currentPos = parseInt(main.style.transform.replace('translateX(', '')) || 0;
                    const nextPos = currentPos + velocity;
                    const maxScroll = box.offsetWidth - main.offsetWidth;
                    const boundedPos = Math.max(maxScroll, Math.min(0, nextPos));
                    
                    main.style.transform = `translateX(${boundedPos}px)`;
                    
                    animationId = requestAnimationFrame(decelerate);
                } else {
                    
                    main.style.transition = 'transform 0.3s';
                    snapToNearest();
                }
            };
            
            decelerate();
        }

        function snapToNearest() {
            const currentPos = parseInt(main.style.transform.replace('translateX(', '')) || 0;
            const itemWidth = main.offsetWidth / 5; // 假设有5个等宽的项目
            const snapIndex = Math.round(-currentPos / itemWidth);
            const snapPos = -snapIndex * itemWidth;
            
            main.style.transform = `translateX(${snapPos}px)`;
        }

        box.addEventListener('touchstart', handleTouchStart);
        box.addEventListener('touchmove', handleTouchMove, { passive: false });
        box.addEventListener('touchend', handleTouchEnd);
    </script>
</body>
</html>
周枫涟
2025-01-10

禁用滚动,自己监听触摸事件来控制容器滚动

公羊俊德
2025-01-10

在JavaScript中,控制移动端 overflow: scroll 容器的滑动速度通常不是直接通过CSS或原生JavaScript属性来实现的。这是因为滚动行为通常由浏览器的默认行为处理,而这些行为在不同的设备和浏览器上可能会有所不同。

然而,你可以通过监听滚动事件和触摸事件(如 touchstarttouchmovetouchend),然后手动计算并限制滚动速度来实现这一点。以下是一个基本的示例,展示了如何通过JavaScript来限制滚动速度:

### 回答

你可以使用以下JavaScript代码来控制移动端 `.box` 区域的滑动最大速度:

document.addEventListener('DOMContentLoaded', function () {

const box = document.querySelector('.box');

let startX, startY, scrollTop, scrollLeft, time;

box.addEventListener('touchstart', function (e) {
    const touch = e.touches[0];
    startX = touch.clientX;
    startY = touch.clientY;
    scrollTop = box.scrollTop;
    scrollLeft = box.scrollLeft;
    time = Date.now();
});

box.addEventListener('touchmove', function (e) {
    const touch = e.touches[0];
    const deltaX = touch.clientX - startX;
    const deltaY = touch.clientY - startY;
    const currentTime = Date.now();
    const timeDiff = currentTime - time;

    // 计算速度
    const velocityX = deltaX / timeDiff;
    const velocityY = deltaY / timeDiff;

    // 设置最大速度(例如,每秒最多滚动100像素)
    const maxVelocity = 100;

    // 限制速度
    const limitedVelocityX = Math.sign(velocityX) * Math.min(Math.abs(velocityX), maxVelocity);
    const limitedVelocityY = Math.sign(velocityY) * Math.min(Math.abs(velocityY), maxVelocity);

    // 计算新的滚动位置
    const newScrollTop = scrollTop - limitedVelocityY * (timeDiff / 1000);
    const newScrollLeft = scrollLeft - limitedVelocityX * (timeDiff / 1000);

    // 应用新的滚动位置(注意:这里直接设置scrollTop和scrollLeft可能会导致跳动,
    // 实际应用中可能需要使用平滑滚动或请求动画帧)
    box.scrollTop = Math.min(Math.max(newScrollTop, 0), box.scrollHeight - box.clientHeight);
    box.scrollLeft = Math.min(Math.max(newScrollLeft, 0), box.scrollWidth - box.clientWidth);

    // 更新起始点和时间
    startX = touch.clientX;
    startY = touch.clientY;
    time = currentTime;
});

});


**注意**:

1. 上面的代码直接修改了 `scrollTop` 和 `scrollLeft`,这可能会导致滚动行为看起来不那么平滑。在实际应用中,你可能需要使用平滑滚动技术或 `requestAnimationFrame` 来改进这一点。
2. 滚动速度的限制是通过计算手指移动的速度并将其限制在一个最大速度来实现的。这里使用了一个简单的线性速度计算,实际应用中可能需要更复杂的算法来处理不同的滚动情况(如惯性滚动)。
3. 由于不同设备和浏览器的触摸事件处理可能会有所不同,因此上述代码可能需要在不同的设备和浏览器上进行测试和调整。
 类似资料:
  • 问题内容: 我正在写容易的太空入侵者,并且在移动船只时遇到问题。基本上我先改变船的位置,然后再改变。如果变化很大,那就更像是跳跃而不是移动。如果更改很小,则动画会更平滑,但会变得更慢。有什么解决办法吗? 我正在使用JPanel并使用。 @edit:我不太了解我的电脑如何流畅地显示普通(新)游戏,而简单的绘图图像的帧率却很低。这就是为什么我认为这是软件问题而不是硬件问题。因此,也许我做了一些会影响帧

  • 本文向大家介绍Android开发控制ScrollView滑动速度的方法,包括了Android开发控制ScrollView滑动速度的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Android开发控制ScrollView滑动速度的方法。分享给大家供大家参考,具体如下: 前言 由于各个Android平板触摸屏的材质不一样,滑动效果会有一些区别,有的比较灵敏,有的比较迟钝,这里就遇到了要求

  • 本文向大家介绍js用拖动滑块来控制图片大小的方法,包括了js用拖动滑块来控制图片大小的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了js用拖动滑块来控制图片大小的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的javascript程序设计有所帮助。

  • 更新 引用:perfecto mobile和device 我正在研究一个基于云的移动测试解决方案,应该支持iOS和Android。它要求连接的移动设备从浏览器处理。 我了解到移动设备有一种代理程序(它要求设备根植)安装, 将移动屏幕流到浏览器 并注入事件 有没有其他方法可以在不破坏设备的情况下实现这一点? 任何指针都是赞赏的。 更新1: 这个问题接近我正在寻找的。 更新2:我已经为Android设

  • 本文向大家介绍js实现移动端导航点击自动滑动效果,包括了js实现移动端导航点击自动滑动效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了js实现移动端导航点击滑动效果的具体代码,供大家参考,具体内容如下 移动端模拟导航可点击自动滑动 0.1.4。 导航可左右滑动,可点击边缘的一个,自动滚动下一个到可视范围【依赖于iscroll.js】。 废话不多说直接上代码: 截图: 提供demo

  • 本文向大家介绍JS div匀速移动动画与变速移动动画代码实例,包括了JS div匀速移动动画与变速移动动画代码实例的使用技巧和注意事项,需要的朋友参考一下 1.匀速移动代码 2.变速移动代码 common.js 以上所述是小编给大家介绍的JS div匀速移动动画与变速移动动画详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对呐喊教程网站的支持!

  • 本文向大家介绍JavaScript实现移动端滑动选择日期功能,包括了JavaScript实现移动端滑动选择日期功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了JavaScript实现滑动选择日期的具体代码,供大家参考,具体内容如下 更多关于滑动效果的专题,请点击下方链接查看: javascript滑动操作汇总 jquery滑动操作汇总 以上就是本文的全部内容,希望对大家的学习有所

  • 由于产品的有多个变体属性,每个属性又对应很多图片,图片太多了,于是我添加了代码来实现点击产品的选项值,来展示对应alt值的图片,而其他未被选择的选项值对应的图片隐藏。PC端完成了此效果,但是移动端没有完全响应。移动端采用的是轮播图方式flickity控制。当图片滑完时会显示空白,正常效果应该是滑到最后一张不能滑动了,或者自动跳转到第一张图片,请问如何实现这个效果? //这是加的判断,根据产品变体的