Rumah > hujung hadapan web > tutorial js > Supercharge Animasi Web Anda: Optimumkan requestAnimationFrame Seperti Pro

Supercharge Animasi Web Anda: Optimumkan requestAnimationFrame Seperti Pro

DDD
Lepaskan: 2024-09-26 22:23:30
asal
253 orang telah melayarinya

Supercharge Your Web Animations: Optimize requestAnimationFrame Like a Pro

Animasi yang lancar dan berprestasi adalah penting dalam aplikasi web moden. Walau bagaimanapun, mengurusnya secara tidak betul boleh membebankan utas utama penyemak imbas, menyebabkan prestasi lemah dan animasi janky. requestAnimationFrame (rAF) ialah API penyemak imbas yang direka untuk menyegerakkan animasi dengan kadar segar semula paparan, memastikan pergerakan yang lebih lancar berbanding alternatif seperti setTimeout. Tetapi menggunakan rAF dengan cekap memerlukan perancangan yang teliti, terutamanya apabila mengendalikan berbilang animasi.

Dalam artikel ini, kami akan meneroka cara mengoptimumkan requestAnimationFrame dengan memusatkan pengurusan animasi, memperkenalkan kawalan FPS dan memastikan urutan utama penyemak imbas responsif.


Memahami FPS dan Mengapa Ia Penting

Bingkai sesaat (FPS) adalah penting apabila membincangkan prestasi animasi. Kebanyakan skrin dimuat semula pada 60 FPS, bermakna requestAnimationFrame dipanggil 60 kali sesaat. Untuk mengekalkan animasi yang lancar, penyemak imbas mesti menyelesaikan kerjanya dalam masa kira-kira 16.67 milisaat setiap bingkai.

Jika terlalu banyak tugas dijalankan dalam satu bingkai, penyemak imbas mungkin terlepas masa bingkai sasarannya, menyebabkan bingkai tergagap atau terjatuh. Menurunkan FPS untuk animasi tertentu boleh membantu mengurangkan beban pada utas utama, memberikan keseimbangan antara prestasi dan kelancaran.

Pengurus Animasi Berpusat dengan Kawalan FPS untuk Prestasi Lebih Baik

Untuk mengurus animasi dengan lebih cekap, kami boleh memusatkan pengendaliannya dengan gelung kongsi dan bukannya mempunyai berbilang panggilan requestAnimationFrame bertaburan di seluruh kod. Pendekatan terpusat meminimumkan panggilan berlebihan dan menjadikannya lebih mudah untuk menambah kawalan FPS.

Kelas AnimationManager berikut membolehkan kami mendaftar dan menyahdaftar tugas animasi sambil mengawal FPS sasaran. Secara lalai, kami menyasarkan 60 FPS, tetapi ini boleh dilaraskan untuk keperluan prestasi.

class AnimationManager {
  private tasks: Set<FrameRequestCallback> = new Set();
  private fps: number = 60; // Target FPS
  private lastFrameTime: number = performance.now();
  private animationId: number | null = null; // Store the animation frame ID

  private run = (currentTime: number) => {
    const deltaTime = currentTime - this.lastFrameTime;

    // Ensure the tasks only run if enough time has passed to meet the target FPS
    if (deltaTime > 1000 / this.fps) {
      this.tasks.forEach((task) => task(currentTime));
      this.lastFrameTime = currentTime;
    }

    this.animationId = requestAnimationFrame(this.run);
  };

  public registerTask(task: FrameRequestCallback) {
    this.tasks.add(task);
    if (this.tasks.size === 1) {
      this.animationId = requestAnimationFrame(this.run); // Start the loop if this is the first task
    }
  }

  public unregisterTask(task: FrameRequestCallback) {
    this.tasks.delete(task);
    if (this.tasks.size === 0 && this.animationId !== null) {
      cancelAnimationFrame(this.animationId); // Stop the loop if no tasks remain
      this.animationId = null; // Reset the ID
    }
  }
}

export const animationManager = new AnimationManager();
Salin selepas log masuk

Dalam persediaan ini, kami mengira deltaTime antara bingkai untuk menentukan sama ada masa yang mencukupi telah berlalu untuk kemas kini seterusnya berdasarkan FPS sasaran. Ini membolehkan kami mengecilkan kekerapan kemas kini untuk memastikan urutan utama penyemak imbas tidak terbeban.


Contoh Praktikal: Menghidupkan Pelbagai Elemen dengan Sifat Berbeza

Mari kita buat contoh di mana kita menganimasikan tiga kotak, setiap satu dengan animasi yang berbeza: satu skala, satu lagi bertukar warna dan yang ketiga berputar.

Ini HTML:

<div id="animate-box-1" class="animated-box"></div>
<div id="animate-box-2" class="animated-box"></div>
<div id="animate-box-3" class="animated-box"></div>
Salin selepas log masuk

Ini CSS:

.animated-box {
  width: 100px;
  height: 100px;
  background-color: #3498db;
  transition: transform 0.1s ease;
}
Salin selepas log masuk

Sekarang, kami akan menambah JavaScript untuk menghidupkan setiap kotak dengan sifat yang berbeza. Satu akan berskala, satu lagi akan menukar warnanya dan yang ketiga akan berputar.

Langkah 1: Menambah Interpolasi Linear (lerp)

Interpolasi linear (lerp) ialah teknik biasa yang digunakan dalam animasi untuk peralihan antara dua nilai dengan lancar. Ia membantu mencipta perkembangan yang beransur-ansur dan lancar, menjadikannya sesuai untuk menskala, mengalihkan atau menukar sifat dari semasa ke semasa. Fungsi ini mengambil tiga parameter: nilai permulaan, nilai tamat dan masa ternormal (t), yang menentukan sejauh mana peralihan itu.

function lerp(start: number, end: number, t: number): number {
  return start + (end - start) * t;
}
Salin selepas log masuk

Langkah 2: Menskalakan Animasi

Kami mulakan dengan mencipta fungsi untuk menghidupkan penskalaan kotak pertama:

function animateScale(
  scaleBox: HTMLDivElement,
  startScale: number,
  endScale: number,
  speed: number
) {
  let scaleT = 0;

  function scale() {
    scaleT += speed;
    if (scaleT > 1) scaleT = 1;

    const currentScale = lerp(startScale, endScale, scaleT);
    scaleBox.style.transform = `scale(${currentScale})`;

    if (scaleT === 1) {
      animationManager.unregisterTask(scale);
    }
  }

  animationManager.registerTask(scale);
}
Salin selepas log masuk

Langkah 3: Animasi Warna

Seterusnya, kami menghidupkan perubahan warna kotak kedua:

function animateColor(
  colorBox: HTMLDivElement,
  startColor: number,
  endColor: number,
  speed: number
) {
  let colorT = 0;

  function color() {
    colorT += speed;
    if (colorT > 1) colorT = 1;

    const currentColor = Math.floor(lerp(startColor, endColor, colorT));
    colorBox.style.backgroundColor = `rgb(${currentColor}, 100, 100)`;

    if (colorT === 1) {
      animationManager.unregisterTask(color);
    }
  }

  animationManager.registerTask(color);
}
Salin selepas log masuk

Langkah 4: Animasi Putaran

Akhir sekali, kami mencipta fungsi untuk memutar kotak ketiga:

function animateRotation(
  rotateBox: HTMLDivElement,
  startRotation: number,
  endRotation: number,
  speed: number
) {
  let rotationT = 0;

  function rotate() {
    rotationT += speed; // Increment progress
    if (rotationT > 1) rotationT = 1;

    const currentRotation = lerp(startRotation, endRotation, rotationT);
    rotateBox.style.transform = `rotate(${currentRotation}deg)`;

    // Unregister task once the animation completes
    if (rotationT === 1) {
      animationManager.unregisterTask(rotate);
    }
  }

  animationManager.registerTask(rotate);
}
Salin selepas log masuk

Langkah 5: Memulakan Animasi

Akhir sekali, kita boleh memulakan animasi untuk ketiga-tiga kotak:

// Selecting the elements
const scaleBox = document.querySelector("#animate-box-1") as HTMLDivElement;
const colorBox = document.querySelector("#animate-box-2") as HTMLDivElement;
const rotateBox = document.querySelector("#animate-box-3") as HTMLDivElement;

// Starting the animations
animateScale(scaleBox, 1, 1.5, 0.02); // Scaling animation
animateColor(colorBox, 0, 255, 0.01); // Color change animation
animateRotation(rotateBox, 360, 1, 0.005); // Rotation animation
Salin selepas log masuk

Nota pada Benang Utama

Apabila menggunakan requestAnimationFrame, adalah penting untuk diingat bahawa animasi berjalan pada urutan utama penyemak imbas. Melebihkan utas utama dengan terlalu banyak tugas boleh menyebabkan penyemak imbas terlepas bingkai animasi, mengakibatkan gagap. Inilah sebabnya mengapa mengoptimumkan animasi anda dengan alatan seperti pengurus animasi terpusat dan kawalan FPS boleh membantu mengekalkan kelancaran, walaupun dengan berbilang animasi.


Kesimpulan

Mengurus animasi dengan cekap dalam JavaScript memerlukan lebih daripada sekadar menggunakan requestAnimationFrame. Dengan memusatkan animasi dan mengawal FPS, anda boleh memastikan animasi yang lebih lancar dan berprestasi sambil memastikan urutan utama responsif. Dalam contoh ini, kami menunjukkan cara mengendalikan berbilang animasi dengan satu AnimationManager, menunjukkan cara mengoptimumkan prestasi dan kebolehgunaan. Walaupun kami menumpukan pada mengekalkan FPS yang konsisten untuk kesederhanaan, pendekatan ini boleh dikembangkan untuk mengendalikan nilai FPS yang berbeza untuk pelbagai animasi, walaupun itu di luar skop artikel ini.

Repo Github : https://github.com/JBassx/rAF-optimization
StackBlitz : https://stackblitz.com/~/github.com/JBassx/rAF-optimization

LinkedIn : https://www.linkedin.com/in/josephciullo/

Atas ialah kandungan terperinci Supercharge Animasi Web Anda: Optimumkan requestAnimationFrame Seperti Pro. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan