Leon's blog Leon's blog
首页
前端
场景
技术
更多
关于
收藏
索引
GitHub (opens new window)

Leon Yu

做一个有个性的开发者~
首页
前端
场景
技术
更多
关于
收藏
索引
GitHub (opens new window)
  • 场景
  • ResizeObserver防抖优化性能
  • useAbortableRequest
  • requestAnimation与滚动
    • 支持promise的并发
    • 单点登录场景与理解
    • 前端路由
    • 场景
    leon yu
    2024-06-15
    目录

    requestAnimation与滚动

    # 对于 requestAnimationFrame 的理解

    window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

    这种方式比传统的setTimeout更加精准,因为requestAnimationFrame会在浏览器重绘之前执行,从而减少了时间误差。

    requestAnimationFrame (opens new window)

    # 使用 requestAnimationFrame写一个精准的定时器

    /**
     * 使用requestAnimationFrame实现的精准定时器
     * @param {Function} callback - 需要执行的回调函数
     * @param {number} delay - 延迟时间,单位为毫秒
     */
    function rafTimer(callback, delay) {
      let start = null;
      let rafId;
    
      // requestAnimationFrame的回调函数
      const step = (timestamp) => {
        // 初始化开始时间
        if (!start) start = timestamp;
        // 计算经过的时间
        const progress = timestamp - start;
        // 如果经过的时间大于等于设置的延迟时间,则执行回调函数
        if (progress >= delay) {
          callback();
        } else {
          // 否则继续下一帧
          rafId = requestAnimationFrame(step);
        }
      };
    
      // 开始执行
      rafId = requestAnimationFrame(step);
    
      // 返回一个函数,用于取消定时器
      return () => {
        cancelAnimationFrame(rafId);
      };
    }
    
    // 使用示例
    const cancelRafTimer = rafTimer(() => {
      console.log('执行回调');
    }, 2000);
    
    // 如果需要取消定时器,可以调用返回的函数
    // cancelRafTimer();
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40

    # 使用 requestAnimationFrame 实现滚动

    /**
     * 使用requestAnimationFrame实现平滑滚动
     * @param {Element} element - 需要滚动的元素
     * @param {number} target - 目标滚动位置
     * @param {number} duration - 滚动持续时间,单位为毫秒
     */
    function smoothScroll(element, target, duration) {
      let start = element.scrollTop,
          change = target - start,
          currentTime = 0,
          increment = 20;
    
      const animateScroll = function() {
        // 增加时间
        currentTime += increment;
        // 计算当前动画进度
        const val = easeInOutQuad(currentTime, start, change, duration);
        // 设置滚动位置
        element.scrollTop = val;
        // 如果当前时间小于总持续时间,继续下一帧动画
        if (currentTime < duration) {
          requestAnimationFrame(animateScroll);
        }
      };
    
      // 缓动函数 - 二次方的缓动(t^2)
      function easeInOutQuad(t, b, c, d) {
        t /= d / 2;
        if (t < 1) return c / 2 * t * t + b;
        t--;
        return -c / 2 * (t * (t - 2) - 1) + b;
      }
    
      animateScroll();
    }
    
    // 使用示例
    // 假设有一个元素需要滚动,id为"scrollContainer"
    const scrollContainer = document.getElementById('scrollContainer');
    // 调用smoothScroll函数,滚动到100px的位置,持续时间为500毫秒
    smoothScroll(scrollContainer, 100, 500);
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    这段代码定义了一个smoothScroll函数,它接收三个参数:需要滚动的元素、目标滚动位置和滚动持续时间。函数内部使用了requestAnimationFrame来实现平滑滚动效果,并通过缓动函数easeInOutQuad来计算每一帧的滚动位置,使得滚动动画更加平滑自然。使用时只需传入相应的参数即可实现平滑滚动效果。

    最近更新~: 2024/08/19, 01:05:55
    useAbortableRequest
    支持promise的并发

    ← useAbortableRequest 支持promise的并发→

    最近更新
    01
    应用层
    01-11
    02
    计算机网络和因特网
    12-22
    03
    关于
    12-22
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 主题来自 Evan Xu | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式