the-way-of-code

Thêm Hiệu Ứng Visual Vào Dự Án

Tài liệu này hướng dẫn cách thêm hiệu ứng visual mới vào dự án. Dự án sử dụng một hệ thống animation module hóa, hỗ trợ cả Three.js và Canvas 2D.

Mục Lục

Thiết Lập Môi Trường

  1. Three.js: Dự án sử dụng Three.js r128
    • Phiên bản local được lưu trong /assets/js/three.min.js
    • Có thể tải phiên bản mới nhất từ https://threejs.org/build/three.min.js
  2. Trình duyệt hiện đại:
    • Hỗ trợ ES6 modules
    • Hỗ trợ WebGL
    • Các tính năng JavaScript hiện đại
  3. Kiến thức cần thiết:
    • JavaScript/ES6
    • Three.js hoặc Canvas 2D
    • Hiểu biết về module system

Kiến Trúc Hệ Thống

Hệ thống animation được tổ chức theo kiến trúc module như sau:

assets/
  ├── js/
  │   ├── three.min.js              # Three.js local library (r128)
  │   ├── animations/
  │   │   ├── animation-utils.js      # Tiện ích và cấu hình dùng chung
  │   │   ├── animation-manager.js    # Quản lý animation module
  │   │   ├── chapter1-interference.js
  │   │   ├── chapter2-tessellation.js
  │   │   ├── chapter3-binaryflow.js
  │   │   ├── chapter4-verticalbars.js
  │   │   ├── chapter5-emptyvessel.js
  │   │   ├── chapter6-particleflower.js
  │   │   ├── chapter7-pinecone.js
  │   │   ├── chapter8-waterascii.js
  │   │   ├── chapter9-canyonflows.js
  │   │   ├── chapter10-yinyang.js
  │   │   ├── chapter11-voidarchitecture.js
  │   │   ├── chapter12-metamorphosis.js
  │   │   ├── chapter13-doublehelix.js
  │   │   ├── chapter14-formlesswaves.js
  │   │   ├── chapter15-watchfulwaves.js
  │   │   ├── chapter16-morphingcontours.js
  │   │   ├── chapter17-kaleidoscope.js
  │   │   └── chapter18-hasharchitecture.js
  │   │   ├── chapter19-vortexparticles.js
  │   │   ├── chapter20-flowingpaths.js
  │   │   ├── chapter21-bouncingpointcloud.js
  │   └── animations-import.js        # Bridge giữa module và global scope
  │   ├── metadata/
  │   │   ├── chapter1-metadata.js
  │   │   ├── chapter2-metadata.js
  │   │   ├── chapter3-metadata.js
  │   │   └── index.js
  │   ├── loaders/
  │   │   └── index.js

Các Thành Phần Chính

  1. animation-utils.js: Chứa cấu hình và các hàm tiện ích dùng chung:
    • Màu sắc và thiết lập theme
    • Kích thước container
    • Trạng thái loading
    • Xử lý lỗi
    • Tiện ích dọn dẹp tài nguyên
  2. animation-manager.js: Hệ thống quản lý animation module trung tâm:
    • Khởi tạo animation dựa trên chapter ID
    • Sử dụng dynamic import qua loader map (loaders/index.js)
    • Metadata được tách riêng qua metadata/index.js
    • Xử lý trạng thái loading
    • Quản lý việc dọn dẹp
    • Cung cấp metadata
  3. loaders/index.js: Map tên animation sang dynamic import module tương ứng.
    • Dễ mở rộng, không cần switch-case dài.
  4. metadata/index.js: Tổng hợp metadata từng chương từ các file nhỏ.
    • Dễ bảo trì, chỉ cần thêm file metadata mới cho mỗi chương.
  5. animations-import.js: Bridge giữa hệ thống module và global scope:
    • Import animationManager từ module system
    • Expose animationManager ra global scope để các file khác có thể sử dụng

Hướng Dẫn Từng Bước

  1. Tạo Module Animation
    // assets/js/animations/chapter-X-name.js
    import animationUtils from './animation-utils.js';
       
    const chapterXAnimation = {
      // Thiết lập riêng cho animation này
      settings: {
        colors: animationUtils.colors,  // Sử dụng màu dùng chung
        // Các thiết lập khác cho chapter
      },
         
      init(container) {
        // Khởi tạo animation
        if (!container) return null;
           
        // Hiển thị loader trong quá trình thiết lập
        const loader = container.querySelector('.animation-loader');
           
        // Thiết lập animation
        // ...
           
        // Ẩn loader khi animation đã sẵn sàng
        animationUtils.fadeOutLoader(container);
           
        // Trả về object có hàm cleanup
        return {
          cleanup: () => {
            // Dọn dẹp tài nguyên
          }
        };
      }
    };
       
    export default chapterXAnimation;
    
  2. Cập Nhật Metadata
    • Tạo file mới trong assets/js/animations/metadata/chapterX-metadata.js:
      export default {
        name: "animationName",
        themes: "Theme 1, Theme 2, ...",
        visualization: "Mô tả visualization",
        description: "Mô tả chi tiết về ý nghĩa của animation"
      };
      
    • Thêm import vào assets/js/animations/metadata/index.js:
      import chapterX from './chapterX-metadata.js';
      export default {
        ...existing code...
        X: chapterX,
      };
      
  3. Thêm Loader cho Animation
    • Thêm vào assets/js/animations/loaders/index.js:
      animationName: () => import('../chapterX-animationfile.js'),
      
  4. Không cần sửa switch-case trong animation-manager.js
    • animation-manager sẽ tự động lấy loader và metadata qua map.
  5. Cập Nhật Main.js
    // Trong main.js, thêm điều kiện cho chapter mới
    if (data.id === 1 || data.id === 2 || data.id === X) {  // Thêm số chapter của bạn
      contentHTML += `
        <div class="animation-container" id="animation-container">
          <div class="animation-loader">
            <div>
              <span class="loading-text">Đang tải hiệu ứng visual...</span>
              <noscript>JavaScript cần được bật để hiển thị hiệu ứng</noscript>
            </div>
          </div>
        </div>
      `;
    }
    

Ví Dụ: Chuyển Đổi Component React Sang Module

Khi bạn có một component React (ví dụ từ thư mục raw_animation/) và muốn chuyển đổi thành module JavaScript cho dự án, hãy làm theo các bước sau:

  1. Chuyển Đổi Cấu Hình
    // Từ React props
    const initialZoom = 6;
       
    // Thành
    settings: {
      initialZoom: 6,
      waveSourceCount: 5,
      resolution: 32,
      colors: animationUtils.colors,
      lineOpacity: 0.4
    }
    
  2. Chuyển Đổi Logic Khởi Tạo
    // Từ React useEffect
    useEffect(() => {
      if (!containerRef.current) return;
      // ...code khởi tạo
    }, []);
       
    // Thành
    init(container) {
      if (!container) return null;
      // ...code khởi tạo giữ nguyên
    }
    
  3. Chuyển Đổi Cleanup
    // Từ React cleanup
    return () => {
      // ...code dọn dẹp
    };
       
    // Thành
    return {
      cleanup: () => {
        // ...code dọn dẹp giữ nguyên
      }
    };
    
  4. Chuyển Đổi Styles
    // Từ React inline styles
    style=
       
    // Thành CSS trong animations.css
    .animation-container {
      margin: 0;
      background: #F0EEE6;
      /* ... */
    }
    
  5. Thêm Export Module
    // Cuối file
    export default chapterAnimation;
    

Quy Tắc Thực Hành

  1. Quản Lý Cấu Hình
    • Sử dụng màu sắc từ animation-utils.js
    • Giữ các thiết lập riêng trong module animation
    • Mô tả rõ mục đích của từng thiết lập
  2. Quản Lý Tài Nguyên
    • Luôn implement cleanup đầy đủ
    • Giải phóng tài nguyên Three.js
    • Gỡ bỏ event listeners
    • Dọn dẹp canvas
  3. Hiệu Năng
    • Sử dụng requestAnimationFrame cho animation
    • Xử lý resize hợp lý
    • Tính đến device pixel ratio
    • Tối ưu vòng lặp render
  4. Xử Lý Lỗi
    • Kiểm tra dependencies cần thiết
    • Cung cấp fallback khi có thể
    • Sử dụng tiện ích xử lý lỗi dùng chung
  5. Tổ Chức Code
    • Giữ tính module hóa cho animation
    • Tái sử dụng tiện ích dùng chung
    • Tuân thủ quy ước đặt tên
    • Viết tài liệu cho thuật toán phức tạp
  6. Module System
    • Sử dụng ES6 modules cho import/export
    • Đảm bảo import và export đúng cú pháp
    • Khi chỉnh sửa cấu trúc module, cập nhật đồng thời trong animation-manager.js
    • Sử dụng dynamic import để tải animation theo demand