Skip to content

useRaf 🎬

はじめに

アニメーションをスムーズにしたいですか?ブラウザの再描画タイミングで正確にコードを実行したいですか?useRaf があなたの最適なパートナーです!🎯

この Hook は、便利な requestAnimationFrame の呼び出しとキャンセル機能を提供し、アニメーションのリズムを簡単に制御でき、カクツキの悩みから解放されます!

コードデモ

基本的な使い方 ⚡

次のブラウザ再描画の前にコードを実行し、ブラウザのレンダリングリズムと完全に一致させます:

js
import { useRaf } from '@vant/use';

export default {
  setup() {
    let count = 0;
    
    // 次のフレームで実行、1回だけ実行
    useRaf(() => {
      console.log(`第 ${++count} 回実行`); // 1回だけ実行
      console.log('🎬 アニメーション開始!');
    });
  },
};

ループアニメーション 🔄

ループモードを有効にして、連続したアニメーション効果を作成します:

js
import { useRaf } from '@vant/use';

export default {
  setup() {
    let count = 0;
    
    const cancelRaf = useRaf(
      () => {
        console.log(`🎭 第 ${++count} フレーム`);
        
        // 5回実行したら停止
        if (count === 5) {
          console.log('🎬 アニメーション終了!');
          cancelRaf();
        }
      },
      {
        isLoop: true,    // 开启循环模式
        interval: 100,   // 每 100ms 执行一次
      },
    );
  },
};

元素动画控制 🎨

DOM 操作と組み合わせて滑らかな要素アニメーションを作成:

js
import { ref } from 'vue';
import { useRaf } from '@vant/use';

export default {
  setup() {
    const elementRef = ref();
    let position = 0;
    
    const startAnimation = () => {
      const cancelRaf = useRaf(
        () => {
          position += 2;
          
          if (elementRef.value) {
            elementRef.value.style.transform = `translateX(${position}px)`;
          }
          
          // 移动到 200px 时停止
          if (position >= 200) {
            console.log('🎯 动画完成!');
            cancelRaf();
          }
        },
        {
          isLoop: true,
        },
      );
    };
    
    return {
      elementRef,
      startAnimation,
    };
  },
};

性能监控 📊

利用 RAF 监控页面性能:

js
import { useRaf } from '@vant/use';

export default {
  setup() {
    let frameCount = 0;
    let lastTime = performance.now();
    
    const cancelRaf = useRaf(
      () => {
        frameCount++;
        const currentTime = performance.now();
        
        // 每秒计算一次 FPS
        if (currentTime - lastTime >= 1000) {
          const fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
          console.log(`📊 当前 FPS: ${fps}`);
          
          frameCount = 0;
          lastTime = currentTime;
        }
      },
      {
        isLoop: true,
      },
    );
    
    // 10 秒后停止监控
    setTimeout(() => {
      cancelRaf();
      console.log('📊 性能监控结束');
    }, 10000);
  },
};

响应式动画 📱

根据设备性能调整动画频率:

js
import { useRaf } from '@vant/use';

export default {
  setup() {
    // 检测设备性能
    const isLowPerformance = navigator.hardwareConcurrency <= 2;
    const animationInterval = isLowPerformance ? 32 : 16; // 低性能设备降低帧率
    
    let rotation = 0;
    const elementRef = ref();
    
    const startRotation = () => {
      const cancelRaf = useRaf(
        () => {
          rotation += isLowPerformance ? 2 : 4; // 低性能设备减慢动画
          
          if (elementRef.value) {
            elementRef.value.style.transform = `rotate(${rotation}deg)`;
          }
          
          if (rotation >= 360) {
            rotation = 0;
          }
        },
        {
          isLoop: true,
          interval: animationInterval,
        },
      );
      
      return cancelRaf;
    };
    
    return {
      elementRef,
      startRotation,
    };
  },
};

API 参考

型定義

ts
function useRaf(
  callback: () => void,
  options?: {
    interval?: number;
    isLoop?: boolean;
  },
): () => void;

パラメータ

パラメータ説明デフォルト値
callback実行するコールバック関数() => void-
options設定オプションRafOptions{}

RafOptions

属性説明デフォルト値
interval実行間隔(ミリ秒)、ループモードでのみ有効number0
isLoopループモードを有効にするかどうかbooleanfalse

戻り値

説明
() => voidアニメーションループを停止するキャンセル関数

实际应用场景

🎮 游戏开发

  • 游戏循环渲染
  • 角色移动动画
  • 粒子效果系统

🎨 UI 动画

  • 页面过渡效果
  • 加载动画
  • 滚动视差效果

📊 数据可视化

  • 图表动画更新
  • 实时数据展示
  • 进度条动画

🔧 性能优化

  • 批量 DOM 更新
  • 防抖动画处理
  • 性能监控工具

最佳实践

✅ 推荐做法

js
// 1. 及时清理动画
const cancelRaf = useRaf(callback, { isLoop: true });
onUnmounted(() => {
  cancelRaf();
});

// 2. 根据设备性能调整
const interval = navigator.hardwareConcurrency <= 2 ? 32 : 16;

// 3. 避免在回调中进行复杂计算
useRaf(() => {
  // 简单的 DOM 操作
  element.style.transform = `translateX(${position}px)`;
});

❌ 避免做法

js
// 1. 忘记清理循环动画
useRaf(callback, { isLoop: true }); // 可能导致内存泄漏

// 2. 在回调中进行复杂计算
useRaf(() => {
  // 複雑な計算は避ける(性能に影響)
  const result = heavyCalculation();
});

// 3. 过度使用循环模式
useRaf(callback, { isLoop: true, interval: 1 }); // 過度に高い頻度

调试技巧

🔍 性能分析

js
// 监控动画性能
let frameTime = 0;
const cancelRaf = useRaf(() => {
  const start = performance.now();
  
  // 你的动画代码
  animateElement();
  
  frameTime = performance.now() - start;
  if (frameTime > 16) {
    console.warn(`⚠️ 动画帧耗时过长: ${frameTime.toFixed(2)}ms`);
  }
}, { isLoop: true });

🐛 调试工具

js
// 添加调试信息
const debugRaf = (callback, options) => {
  console.log('🎬 RAF 动画开始', options);
  
  return useRaf(() => {
    console.log('📽️ 执行动画帧');
    callback();
  }, options);
};

ブラウザ互換性

ブラウザサポートバージョン
Chrome✅ 10+
Firefox✅ 4+
Safari✅ 6+
Edge✅ 12+
IE❌ サポートなし

関連ドキュメント

🎯 コア機能

🎨 スタイル関連

🔧 開発ツール

📱 モバイル最適化

🎪 高度な使い方

Vant に基づく企業向けモバイルソリューション