You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React项目中如何为scrollIntoView的smooth行为设置滚动时长?

自定义React元素滚动速度的实现方案

原生的scrollIntoView({ behavior: 'smooth' })由浏览器控制滚动速度,无法直接自定义。要实现更慢的滚动效果,需要手动编写平滑滚动逻辑,以下是具体实现方法:

方法一:自定义平滑滚动函数(通用方案)

通过requestAnimationFrame逐帧计算滚动位置,通过控制总滚动时长来调整速度——时长数值越大,滚动越慢。同时加入缓动函数让滚动过程更自然:

const scrollToElementSlowly = () => {
  const element = document.getElementById('element') as HTMLDivElement;
  if (!element) return;

  // 计算目标位置:元素相对视口的top值 + 当前页面滚动距离
  const targetPosition = element.getBoundingClientRect().top + window.pageYOffset;
  const startPosition = window.pageYOffset;
  const scrollDistance = targetPosition - startPosition;
  const totalDuration = 2000; // 滚动总时长,单位ms,数值越大速度越慢
  let startTimestamp: number | null = null;

  const animateScroll = (timestamp: number) => {
    if (!startTimestamp) startTimestamp = timestamp;
    // 计算滚动进度(范围0-1)
    const progress = Math.min((timestamp - startTimestamp) / totalDuration, 1);
    // 使用ease-in-out缓动函数,让滚动开头和结尾更平缓
    const easedProgress = progress < 0.5 
      ? 2 * progress * progress 
      : 1 - Math.pow(-2 * progress + 2, 2) / 2;
    // 更新页面滚动位置
    window.scrollTo(0, startPosition + scrollDistance * easedProgress);
    // 未完成滚动则继续下一帧动画
    if (progress < 1) {
      window.requestAnimationFrame(animateScroll);
    }
  };

  window.requestAnimationFrame(animateScroll);
};

方法二:结合React useRef(符合React最佳实践)

在React项目中,建议使用useRef获取元素,替代getElementById,避免直接操作DOM的副作用:

import { useRef } from 'react';

const YourComponent = () => {
  const targetElementRef = useRef<HTMLDivElement>(null);

  const scrollToElementSlowly = () => {
    if (!targetElementRef.current) return;

    const targetPosition = targetElementRef.current.getBoundingClientRect().top + window.pageYOffset;
    const startPosition = window.pageYOffset;
    const scrollDistance = targetPosition - startPosition;
    const totalDuration = 2500; // 调整此值控制滚动速度
    let startTimestamp: number | null = null;

    const animateScroll = (timestamp: number) => {
      if (!startTimestamp) startTimestamp = timestamp;
      const progress = Math.min((timestamp - startTimestamp) / totalDuration, 1);
      const easedProgress = progress < 0.5 
        ? 2 * progress * progress 
        : 1 - Math.pow(-2 * progress + 2, 2) / 2;
      window.scrollTo(0, startPosition + scrollDistance * easedProgress);
      if (progress < 1) {
        window.requestAnimationFrame(animateScroll);
      }
    };

    window.requestAnimationFrame(animateScroll);
  };

  return (
    <div>
      <button onClick={scrollToElementSlowly}>滚动到目标元素</button>
      {/* 目标元素通过ref关联 */}
      <div ref={targetElementRef} className="target-element">需要滚动到的元素</div>
    </div>
  );
};

关键说明

  • 调整totalDuration数值即可控制滚动速度:比如设置为3000(3秒)会比原生smooth滚动慢很多。
  • 缓动函数可按需替换,若不需要缓动效果,直接用progress代替easedProgress即可实现线性滚动。

内容的提问来源于stack exchange,提问作者jesusrlm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 15:47:13