説明:


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;    }}

説明:


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();        });    }}

説明:


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

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

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

説明:


結論

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

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

","image":"http://www.luping.net/uploads/20241022/17296041676717aa472ee02.jpg","datePublished":"2024-11-09T01:12:23+08:00","dateModified":"2024-11-09T01:12:23+08:00","author":{"@type":"Person","name":"luping.net","url":"https://www.luping.net/articlelist/0_1.html"}}
「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > フローフィールド画面

フローフィールド画面

2024 年 11 月 9 日に公開
ブラウズ:684

Flow Field Screen

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

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

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

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



    Flow Fields

説明:

  • すべてのアニメーションが行われる 要素を定義します。
  • 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 = 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  {
            particle.draw(context);
            particle.update();
        });
    }
}

説明:

  • Constructor: キャンバスの寸法、パーティクルの数、およびフロー フィールドを初期化します。
  • 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 の三角関数を組み合わせることで、これらの魅惑的な視覚効果を構築することができます。

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

リリースステートメント この記事は次の場所に転載されています: https://dev.to/ibra-kdbra/flow-field-screen-567c?1 侵害がある場合は、[email protected] に連絡して削除してください。
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3