高校倫理1433840 views
LaTeX957673 views
中学英語809046 views
中学理科1626729 views
世界の国560930 views
英語608453 views
MathPython492025 views
高校国語785873 views
小学社会308762 views
りんご194232 views
Help
Tools

English

RAF による mousemove 最適化の要点

問題

mousemove イベントは高頻度で発火(ミリ秒単位)
毎回 DOM 操作(選択範囲レンダリング)すると性能劣化

解決策

requestAnimationFrame (RAF) で描画を間引く

let rafId: number | null = null

element.addEventListener('mousemove', (event) => {
    // 座標を取得
    const coord = getCoordinate(event)
    
    // RAF がすでにスケジュール済みならスキップ
    if (rafId !== null) return
    
    // 次フレームで描画をスケジュール
    rafId = requestAnimationFrame(() => {
        render(coord)  // 描画処理
        rafId = null
    })
})

RAF と mouseup の競合問題

RAF 実行前に mouseup が発火すると、状態が不整合になる

// ❌ 危険な実装
let start: Coord | null = null

mousemove: rafId = requestAnimationFrame(() => {
    setSelection(start, end)  // start が null の可能性
})

mouseup: start = null  // RAF 実行前にリセット

解決:イベント発火時に値をキャプチャ

mousemove: 
    const capturedStart = start
    const capturedEnd = coord
    
    rafId = requestAnimationFrame(() => {
        if (!capturedStart) return  // 防御的チェック
        setSelection(capturedStart, capturedEnd)
    })

mouseup:
    if (rafId !== null) {
        cancelAnimationFrame(rafId)  // 未実行の RAF をキャンセル
        rafId = null
    }
    start = null

重要ポイント

RAF のスキップ: rafId !== null で重複スケジュールを防ぐ
値のキャプチャ: RAF 内で参照する変数はイベント時点でキャプチャ
RAF のクリーンアップ: mouseup / mousedown で未実行の RAF をキャンセル
防御的 null チェック: RAF 内でも念のためガード

効果

描画頻度: 毎ミリ秒 → 60fps(約 16ms ごと)
不要な DOM 操作を削減
滑らかな UI 更新