3 371 Codepen

Частицы на canvas в виде кружков

Частицы на canvas. Кружки случайно перемещающиеся по холсту с дополнительным эффектом у курсора.

HTML

<canvas id="canvas" class="canvas"></canvas>

CSS

html {
  font: 16px/1.5 'Work Sans', sans-serif;
  color: #444;
}

body {
  background-color: #214;
  padding: 0;
  margin: 0;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

h1 {
  font-size: 5em;
  text-align: center;
  font-weight: 200;
  color: #dce;
  opacity: .1;
}

.canvas {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;
}

JS

'use strict';

var mouse, originx, originy, int, cvs;

/* Safari doesn't support EventTarget :( */
var EventTarget = EventTarget || false;
if (EventTarget) {
  EventTarget.prototype.evt = function (event, callback) {
    return this.addEventListener(event, callback);
  }
}
else {
  window.evt = function (event, callback) {
    return this.addEventListener(event, callback);
  };
  document.evt = function (event, callback) {
    return this.addEventListener(event, callback);
  };
  Element.prototype.evt = function (event, callback) {
    return this.addEventListener(event, callback);
  };
}


function $(elemId) {
    return document.getElementById(elemId);
}

function init() {
    cvs = $("canvas");

    resizeCanvas(cvs);

    window.evt('resize', resizeCanvas, false);
    window.evt("mousemove", function (e) {
        mouse = getMousePos(cvs, e);
        originx = mouse.x;
        originy = mouse.y;
      
    });
    // window.evt("touchmove", function (e) {
    //     originx = e.originalEvent.touches[0].pageX;
    //     originy = e.originalEvent.touches[0].pageY;
    // });

    var network = new Field(0, 0, 50);
    var emit = new Emitter(0, 0, 50);
    
    animateCanvas(cvs, function () {
        network.animate();
        emit.animate();
    });
}

class Point {
    constructor(x, y, canvas, dia) {
        this.canvas = canvas || cvs;
        this.x = x || 0;
        this.y = y || 0;
        this.vx = 0;
        this.vy = 0;
        this.speed = Math.random() * .5 + .2;
        this.angle = Math.random() * 360;
        this.diaSet = dia || 2 + Math.random() * 10;
        this.dia = this.diaSet;
        this.age = 0;
        let hue = Math.floor(Math.random()*360);
        this.fill = 'hsl('+hue+', 95%, 70%)';
        this.line = Math.random() > .5 ? true : false;
    }

    emit(life) {
        let s = this.speed * 2;
        this.angle += Math.random() * 10 - 5;
        this.x += s * Math.cos(this.angle * Math.PI / 180);
        this.y += s * Math.sin(this.angle * Math.PI / 180);
        this.age += 1 / life;
        this.boundary();
    }

    boundary() {
        if (this.x < 0) {
            this.x = this.canvas.width;
        }
        if (this.x > this.canvas.width) {
            this.x = 0;
        }
        if (this.y < 0) {
            this.y = this.canvas.height;
        }
        if (this.y > this.canvas.height) {
            this.y = 0;
        }
    }

    field(life) {
        let s = this.speed;
        this.angle += Math.random() * 10 - 5;
        this.x += s * Math.cos(this.angle * Math.PI / 180);
        this.y += s * Math.sin(this.angle * Math.PI / 180);
        this.age += 1 / life;
        this.boundary();
    }

    shrink(life) {
        this.dia = (1 - this.age) * this.diaSet;
    }

    draw() {
        let ctx = this.canvas.getContext('2d'),
            x = this.x,
            y = this.y,
            dia = this.dia,
            age = this.age;

        ctx.beginPath();
        ctx.fillStyle = this.fill;
        ctx.strokeStyle = this.fill;
        ctx.lineWidth = 2;
        ctx.arc(x, y, dia, 0, 2 * Math.PI);
        ctx.closePath();
        
        this.line !== true ? ctx.fill() : ctx.stroke();
    }
}

class Particle {

    setPosition(x, y) {
        this.x = x;
        this.y = y;
    }

    getPosition(x, y) {
        return {
            x: this.x,
            y: this.y
        };
    }

    spawn(x, y, amount, dia) {

        var arr = [];
        dia = dia || false;

        amount = amount || 1;

        if (amount > 1) {
            for (let i = 0; i < amount; i++) {
                if (dia) {
                    arr.push(new Point(x, y, cvs, dia));
                }
                else {
                    arr.push(new Point(x, y, cvs));
                }
                
            }
        } else {
            arr = new Point(x, y, cvs, dia);
        }

        return arr;
    }
}

// Particle Emitter
class Emitter extends Particle {
    constructor(x, y, life, mouse, dia) {
        super();

        if (mouse === undefined) {
            this.mouse = true;
        } else {
            this.mouse = mouse;
        }

        this.particles = [];
        this.x = x || 0;
        this.y = y || 0;
        this.life = life || 20;
        this.canvas = cvs;
        this.dia = dia || false;
    }

    animate() {
        let particles = this.particles;
        if (this.mouse) {
            this.setPosition(originx, originy);
        }

        let mul = 1;

        for (let i = 0; i < mul; i++) {
            particles.push(this.spawn(this.x, this.y, 1));
        }
        
        if (particles.length > this.life * mul) {
            for (let i = 0; i < mul; i++) {
                particles.shift();
            }
        }

        this.render(this.canvas);
    }
    
    render() {
        let life = this.life;
        let ctx = this.canvas.getContext('2d');
        let particles = this.particles;

        for (let i = 0; i < particles.length; i++) {
            const p = particles[i];
            p.draw();
            p.emit(this.life);
            p.shrink();
        }
    }
}

// Particle Field
class Field extends Particle {
    constructor(x, y, life) {
        super();
        this.particles = [];
        this.canvas = cvs;
        this.x = x || 0;
        this.y = y || 0;
        this.life = life;

        for (let i = 0; i < this.life; i++) {
            let x = Math.random() * cvs.width,
                y = Math.random() * cvs.height;

            this.particles.push(this.spawn(x, y, 1));
        }
    }

    animate() {
        this.render(canvas);
    }

    render(canvas) {
        let ctx = this.canvas.getContext('2d');
        let particles = this.particles;

        for (let i = 0; i < particles.length; i++) {
            const p = particles[i];
            p.draw();
            p.field(this.life);
        }
    }
}

function getMousePos(cvs, evt) {
    var rect = cvs.getBoundingClientRect();
    return {
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    };
}

//
function animateCanvas(canvas, callback) {

    let ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    callback();

    requestAnimationFrame(animateCanvas.bind(null, canvas, callback));
}

//Update canvas size to fill window
function resizeCanvas(canvas) {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    originx = canvas.width / 2;
    originy = canvas.height / 2;
}

init();

Комментарии

  • Facebook
  • Вконтакте

Похожие статьи