js实现canvas粒子飞舞动画效果代码

代码语言:html

所属分类:粒子

代码描述:js实现canvas粒子飞舞动画效果代码

代码标签: 粒子 飞舞 动画 效果

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<html>
<head>
    <style>
        html, body {
            overflow: hidden;
            margin: 0;
        }

        html {
            background: #14191C;
        }

        p {
            position: absolute;
            bottom: 1em;
            width: 100%;
            color: rgba(255, 255, 255, 0.25);
            text-align: center;
            pointer-events: none;
            transition: opacity 1s ease-in-out;
        }
    </style>

</head>
<body>
    <p style="opacity: 0;">
        Click near Boids to disperse group.
    </p>
    <script>
        // start particle simulation
        simulate(
            '2d', {
                init: function() {

                    this.spray(150, function() {
                        return [
                            null,
                            null,
                            Vector.create(
                                this.width * Math.random(),
                                this.height * Math.random()
                            ),
                            Vector.random(1),
                            .75 + (Math.random() * .5),
                            100 * Math.random(), [
                                this.behavior.cohesion(),
                                this.behavior.alignment(),
                                this.behavior.separation(),

                                this.behavior.limit(1 + Math.random()),

                                this.behavior.wrap(5),
                                this.behavior.move()
                            ]
                        ]
                    })

                },
                tick: function() {},
                beforePaint: function() {
                    this.clear();
                },
                paint: function(particle) {

                    var p = particle.position;
                    var v = particle.velocity;
                    var s = particle.stimulated || 0;
                    var l = particle.life;

                    this.paint.circle(p.x, p.y, v.magnitudeSquared, 'hsla(' + v.angle + ',100%,50%,1)');

                },
                afterPaint: function() {
                    // nothing
                },
                action: function(x, y) {

                    // disperse if near
                    this.particles.forEach(function(p) {

                        if (Vector.distanceSquared(p.position, {
                            x: x,
                            y: y
                        }) < 4000) {
                            p.velocity.randomize(100);
                            p.position.x += p.velocity.x;
                            p.position.y += p.velocity.y;
                        }

                    });

                }
            }
        );

        setTimeout(() => {
            document.querySelector('p').style.opacity = 0;
        }, 3000);


























        // "simulate" particle simulation logic
        /**
        * Constants
        */
        PI_2 = Math.PI / 2;
        PI_180 = Math.PI / 180;

        /**
        * Random
        */
        var Random = {
            between: function(min, max) {
                return min + (Math.random() * (max - min));
            }
        }

        /**
        * 2D Vector Class
        */
        function Vector(x, y) {
            this._x = x || 0;
            this._y = y || 0;
        }

        Vector.create = function(x, y) {
            return new Vector(x, y);
        };

        Vector.add = function(a, b) {
            return new Vector(a.x + b.x, a.y + b.y);
        };

        Vector.subtract = function(a, b) {
            return new Vector(a.x - b.x, a.y - b.y);
        };

        Vector.random = function(range) {
            var v = new Vector();
            v.randomize(range);
            return v;
        };

        Vector.distanceSquared = function(a, b) {
            var dx = a.x - b.x;
            var dy = a.y - b.y;
            return dx * dx + dy * dy;
        };

        Vector.distance = function(a, b) {
            var dx = a.x - b.x;
            var dy = a.y - b.y;
            return Math.sqrt(dx * dx + dy * dy);
        };

        Vector.prototype = {
            get x() {
                return this._x;
            },
            get y() {
                return this._y;
            },
            set x(value) {
                this._x = value;
            },
            set y(value) {
                this._y = value;
            },
            get magnitudeSquared() {
                return this._x * this._x + this._y * this._y;
            },
            get magnitude() {
                return Math.sqrt(this.magnitudeSquared);
            },
            get angle() {
                return Math.atan2(this._y, this._x) * 180 / Math.PI;
            },
            clone: function() {
                return new Vector(this._x, this._y);
            },
            add: function(v) {
                this._x += v.x;
                this._y += v.y;
            },
            subtract: function(v) {
                this._x -= v.x;
                this._y -= v.y;
            },
            multiply: function(value) {
                this._x *= value;
                this._y *= value;
            },
            divide: function(value) {
                this._x /= value;
                this._y /= value;
            },
            normalize: function() {
                var magnitude = this.magnitude;
                if (magnitude > 0) {
                    this.divide(magnitude);
                }
            },
            limit: function(treshold) {
                if (this.magnitude > treshold) {
                    this.normalize();
                    this.multiply(treshold);
                }
            },
            randomize: function(amount) {
                amount = amount || 1;
                this._x = amount * 2 * (-.5 + Math.random());
                this._y = amount * 2 * (-.5 + Math.random());
            },
            rotate: function(degrees) {
                var magnitude = this.magnitude;
                var angle = ((Math.atan2(this._x, this._y) * PI_HALF) + degrees) * PI_180;
                this._x = magnitude * Math.cos(angle);
                this._y = magnitude * Math.sin(angle);
            },
            flip: function() {
                var temp = this._y;
                this._y = this._x;
                this._x = temp;
            },
            invert: function() {
                this._x = -this._x;
                this._y = -this._y;
            },
            toString: function() {
                return this._x + ', ' + this._y;
            }
        }

        /**
        * Particle Class
        */
        function Particle(id, group, position, velocity, size, life, behavior) {

            this._id = id || 'default';
            this._group = group || 'default';

            this._position = position || new Vector();
            this._velocity = velocity || new Vector();
            this._size = size || 1;
            this._life = Math.round(life || 0);

            this._behavior = behavior || [];

        }

        Particle.prototype = {
            get id() {
                return this._id;
            },
            get group() {
                return this._group;
            },
            get life() {
                return this._life;
            },
            get size() {
                return this._size;
            },
            set size(size) {
                this._size = size;
            },
            get position() {
                return this._position;
            },
            get velocity() {
                return this._velocity;
            },
            update: function(stage) {

                this._life++;

                var i = 0;
                var l = this._behavior.length;

                for (; i < l; i++) {
                    this._behavior[i].call(stage, this);
                }

            },
            toString: function() {
                return 'Particle(' + this._id + ') ' + this._life + ' pos: ' + this._position + ' vec: ' + this._velocity;
            }
        }

        // setup DOM
        function simulate(dimensions, options) {

            // private vars
            var particles = [];
            var destroyed = [];
            var update = update || function() {};
            var stage = stage || function() {};
            var canvas;
            var context;

            if (!options) {
                console.error('"options" object must be defined');
                return;
            }

            if (!options.init) {
                console.error('"init" function must be defined');
                return;
            }

            if (!options.paint) {
                console.error('"paint" function must be defined');
                return;
            }

            if (!options.tick) {
                options.tick = function() {};
            }

            if (!options.beforePaint) {
                options.beforePaint = function() {};
            }

            if (!options.afterPaint) {
                options.afterPaint = function() {};
            }

            if (!options.action) {
                options.action = function() {};
            }

            if (document.readyState === 'interactive') {
                setup();
            } else {
                document.addEventListener('DOMContentLoaded', setup);
            }

            // resizes canvas to fit window dimensions
            function fitCanvas() {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
            }

            // create canvas for drawing
            function setup() {

                // create
                canvas = document.createElement('canvas');
                document.body.appendChild(canvas);

                // correct canvas size on window resize
                window.addEventListener('resize', fitCanvas);

                // go
                go();
            }

            // canvas has been attached, let's go!
            function go() {

                // set initial canvas size
                fitCanvas();

                // get context for drawing
                context = canvas.getContext(dimensions);

                // simulation update loop
                function act() {

                    // update particle states
                    var i = 0;
                    var l = particles.length;
                    var p;
                    for (; i < l; i++) {
                        particles[i].update(this);
                    }

                    // clean destroyed particles
                    while (p = destroyed.pop()) {

                        do {

                            // has not been found in destroyed array?
                            if (p !== particles[i]) {
                                continue;
                            }

                            // remove particle
                            particles.splice(i, 1);

                        } while (i-- >= 0)
                        }

                    // repaint context
                    options.beforePaint.call(this);

                    // repaint particles
                    i = 0;
                    l = particles.length;
                    for (; i < l; i++) {
                        options.paint.call(this, particles[i]);
                    }

                    // after particles have been painted
                    options.afterPaint.call(this);
                }

                function tick() {

                    // call update method, this allows for inserting particles later on
                    options.tick.call(this);

                    // update particles here
                    act();

                    // on to the next frame
                    window.requestAnimationFrame(tick);

                }

                /**
                * API
                **/
                function clear() {
                    context.clearRect(0, 0, canvas.width, canvas.height);
                }

                function destroy(particle) {
                    destroyed.push(particle);
                }

                function add(id, group, position, velocity, size, life, behavior) {
                    particles.push(new Particle(id, group, position, velocity, size, life, behavior));
                }

                function spray(amount, config) {
                    var i = 0;
                    for (; i < amount; i++) {
                        add.apply(this, config());
                    }
                }

                function debug(particle) {
                    this.paint.circle(
                        particle.position.x,
                        particle.position.y,
                        particle.size,
                        'rgba(255,0,0,.75)'
                    );
                    context.beginPath();
                    context.moveTo(particle.position.x, particle.position.y);
                    context.lineTo(particle.position.x + (particle.velocity.x * 10), particle.position.y + (particle.velocity.y * 10));
                    context.strokeStyle = 'rgba(255,0,0,.1)'.........完整代码请登录后点击上方下载按钮下载查看

网友评论0