ホームページ  >  記事  >  ウェブフロントエンド  >  フローフィールド画面

フローフィールド画面

Susan Sarandon
Susan Sarandonオリジナル
2024-10-03 20:18:29641ブラウズ

Flow Field Screen

Vanilla JS と HTML Canvas を使用した動的フロー フィールド

抽象的なパーティクル アニメーションに魅了されたことがありますか?これらの流れるような動的なビジュアルは、プレーンな JavaScript と HTML の Canvas 要素を使用する驚くほど簡単な手法で実現できます。この記事では、数千のパーティクルにアニメーションを与え、自然な動きを与えるフロー フィールドを作成するプロセスを詳しく説明します。

1. プロジェクトのセットアップ

まず、キャンバスを設定するための HTML ファイル、スタイルを設定するための CSS ファイル、ロジックを処理するための JavaScript ファイルの 3 つのファイルが必要です。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Flow Fields</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <canvas id="canvas1"></canvas>
    <script src="script.js"></script>
</body>
</html>

説明:

  • を定義します。すべてのアニメーションが行われる要素です。
  • styles.css はキャンバスのスタイルを設定するためにリンクされます。
  • メインのアニメーション ロジックは script.js に含まれています。

2. CSS を使用してキャンバスをスタイル設定する

シンプルなスタイルを追加して、キャンバスの背景を黒にし、すべてのパディングとマージンが削除されていることを確認しましょう。

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

canvas {
    background-color: black;
}

説明:

  • マージンとパディングをゼロに設定すると、キャンバスが画面全体に表示されます。
  • 黒い背景は白い粒子に素晴らしいコントラストを与えます。

3. パーティクル クラス: 魔法の作成

Particle クラスは、アニメーションの中核となる部分です。各パーティクルがキャンバス上を移動し、過去の位置の痕跡を残し、流れるような効果を生み出します。

class Particle {
    constructor(effect) {
        this.effect = effect;
        this.x = Math.floor(Math.random() * this.effect.width);
        this.y = Math.floor(Math.random() * this.effect.height);
        this.speedModifier = Math.floor(Math.random() * 5 + 1);
        this.history = [{ x: this.x, y: this.y }];
        this.maxLength = Math.floor(Math.random() * 200 + 10);
        this.timer = this.maxLength * 2;
        this.colors = ['#4C026B', '#8E0E00', '#9D0208', '#BA1A1A', '#730D9E'];
        this.color = this.colors[Math.floor(Math.random() * this.colors.length)];
    }

    draw(context) {
        context.beginPath();
        context.moveTo(this.history[0].x, this.history[0].y);
        for (let i = 1; i < this.history.length; i++) {
            context.lineTo(this.history[i].x, this.history[i].y);
        }
        context.strokeStyle = this.color;
        context.stroke();
    }

    update() {
        this.timer--;
        if (this.timer >= 1) {
            let x = Math.floor(this.x / this.effect.cellSize);
            let y = Math.floor(this.y / this.effect.cellSize);
            let index = y * this.effect.cols + x;
            let angle = this.effect.flowField[index];

            this.speedX = Math.cos(angle);
            this.speedY = Math.sin(angle);
            this.x += this.speedX * this.speedModifier;
            this.y += this.speedY * this.speedModifier;

            this.history.push({ x: this.x, y: this.y });
            if (this.history.length > this.maxLength) {
                this.history.shift();
            }
        } else if (this.history.length > 1) {
            this.history.shift();
        } else {
            this.reset();
        }
    }

    reset() {
        this.x = Math.floor(Math.random() * this.effect.width);
        this.y = Math.floor(Math.random() * this.effect.height);
        this.history = [{ x: this.x, y: this.y }];
        this.timer = this.maxLength * 2;
    }
}

説明:

  • コンストラクター: 各パーティクルはランダムな位置と移動速度で初期化されます。履歴配列は過去の位置を追跡して軌跡を作成します。
  • draw(): この関数は、履歴に基づいてパーティクルのパスを描画します。パーティクルは視覚効果を高めるカラフルな軌跡を残します。
  • update(): ここでは、流れ場から角度を計算することによって粒子の位置が更新されます。速度と方向は三角関数によって制御されます。
  • reset(): パーティクルが軌跡を終了すると、新しいランダムな位置にリセットされます。

4. エフェクトクラス: アニメーションの構成

Effect クラスは、パーティクルと、パーティクルの動きを制御する流れフィールド自体の作成を処理します。

class Effect {
    constructor(canvas) {
        this.canvas = canvas;
        this.width = this.canvas.width;
        this.height = this.canvas.height;
        this.particles = [];
        this.numberOfParticles = 3000;
        this.cellSize = 20;
        this.flowField = [];
        this.curve = 5;
        this.zoom = 0.12;
        this.debug = true;
        this.init();
    }

    init() {
        this.rows = Math.floor(this.height / this.cellSize);
        this.cols = Math.floor(this.width / this.cellSize);
        for (let y = 0; y < this.rows; y++) {
            for (let x = 0; x < this.cols; x++) {
                let angle = (Math.cos(x * this.zoom) + Math.sin(y * this.zoom)) * this.curve;
                this.flowField.push(angle);
            }
        }
        for (let i = 0; i < this.numberOfParticles; i++) {
            this.particles.push(new Particle(this));
        }
    }

    drawGrid(context) {
        context.save();
        context.strokeStyle = 'white';
        context.lineWidth = 0.3;
        for (let c = 0; c < this.cols; c++) {
            context.beginPath();
            context.moveTo(c * this.cellSize, 0);
            context.lineTo(c * this.cellSize, this.height);
            context.stroke();
        }
        for (let r = 0; r < this.rows; r++) {
            context.beginPath();
            context.moveTo(0, r * this.cellSize);
            context.lineTo(this.width, r * this.cellSize);
            context.stroke();
        }
        context.restore();
    }

    render(context) {
        if (this.debug) this.drawGrid(context);
        this.particles.forEach(particle => {
            particle.draw(context);
            particle.update();
        });
    }
}

説明:

  • コンストラクター: キャンバスの寸法、パーティクルの数、およびフロー フィールドを初期化します。
  • init(): 各グリッド セルの三角関数を組み合わせて、流れ場の角度を計算します。このフィールドはパーティクルの動きに影響を与えます。
  • drawGrid(): デバッグ時に使用される、キャンバスをセルに分割するグリッドを描画します。
  • render(): 各パーティクルの描画メソッドと更新メソッドを呼び出して、キャンバス全体でパーティクルをアニメーション化します。

5. アニメーション ループで命を吹き込む

すべてを機能させるには、キャンバスを継続的にクリアしてパーティクルを再レンダリングするアニメーション ループが必要です。

const effect = new Effect(canvas);

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    effect.render(ctx);
    requestAnimationFrame(animate);
}
animate();

説明:

  • clearRect(): 前のフレームの上に描画されないように、各フレームのキャンバスをクリアします。
  • requestAnimationFrame: animate() 関数を再帰的に呼び出すことでアニメーションを滑らかに保ちます。

結論

Particle クラスと Effect クラスを分解することにより、バニラ JavaScript のみを使用して、流動的でダイナミックな流れフィールド アニメーションを作成しました。 HTML キャンバスのシンプルさと JavaScript の三角関数を組み合わせることで、これらの魅惑的な視覚効果を構築できます。

パーティクルの数、色、流れ場の式を自由にいじって、独自のユニークな効果を作成してください。

以上がフローフィールド画面の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。