<div id="social"></div>
<div id="output"></div>
<div id="canvas"></div>
<div id="proximity"></div>
<div id="proximity2"></div>
<div id="proximity3"></div>
<div id="welcome">
    
    <div class="wlc">
        <h3>Welcome to ProxParticles</h3>
    <div>Make sure to check out the JS, on the top are some Settings to play with.</div>
    </div>
</div>

<div class="msg">Proximity Particles</div>
<div class="msg msg2">by Tibix</div>

html,body{
  background: #292929;
  overflow: hidden;
}

.part{
  position: absolute;
  /* Shadows disabled for Performance */
  /*box-shadow: 0px 0px 20px rgba(20,20,20,0.75), inset 0px 0px 10px rgba(0,0,0,0.75);*/
}

#proximity{
  position: absolute;
  border: 1px solid yellow;
  opacity: 0.3;
  border-radius: 100%;
  transform: translate(-50%, -50%);
}
#proximity2{
  position: absolute;
  border: 1px solid yellow;
  opacity: 0.3;
  border-radius: 100%;
  transform: translate(-50%, -50%);
}
#proximity3{
  position: absolute;
  border: 1px solid yellow;
  opacity: 0.3;
  border-radius: 100%;
  transform: translate(-50%, -50%);
}

#welcome{
    height: 150px;
    width: 300px;
    background: white;
    z-index: 99999;
    position: absolute;
    transform: translate(-50%, -50%);
    top: 50%;
    left: 50%;
    text-align: center;
    font-size: 16px;
    background: rgba(50,50,50,1);
    font-family: 'Courgette', cursive;
    font-color: #292929;
    border-radius: 20px;
    padding: 20px;
    box-shadow: 0px 0px 15px;
}

#welcome>h3{
    text-decoration: underline;
    font-size: 20px;
}

.wlc{
    height: 150px;
    width: 300px;
    background: rgba(150,150,150,1);
    z-index: 999999;
    position: absolute;
    transform: translate(-50%, -50%);
    top: 50%;
    left: 50%;
    border-radius: 20px;
    padding: 10px;
    box-shadow: inset 0px 0px 10px 2px rgba(0,0,0,1);
}

.msg{
  font-family: "Jua", sans-serif;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: 60px;
  color: rgba(0,0,0,0.65);
  text-shadow: 2px 2px 3px rgba(255,255,255,0.1);
  cursor: default;
  pointer-events: none;
  user-select: none;
  z-index: -2;
}

.msg2 {
  transform: translate(-50%, 70%);
  font-size: 32px;
}

.msg:hover{
  cursor: default;
  pointer-events: none;
  user-select: none;
}
// Welcome to ProxParticles
// Hover over the Particles to Push them in the Cursor Direction
// When holding down LMB (Left-Click) the Particles will get Pulled towards the Cursor
// This Pen won't work in Internet Explorer and performs best in Google Chrome

// Settings
var prox = 30;                              // Inner Circle Size
var prox2 = 60;                             // Middle Circle Size
var prox3 = 90;                             // Outer Circle Size
var psm1 = 5;                               // Inner Circle Power
var psm2 = 2.5;                             // Middle Circle Power
var psm3 = 0.75;                            // Outer Circle Power
var particles = 100;                        // Number of Particles (Tested 1-500)
var winW = $(window).width();               // Used to randomize X-Pos
var winH = $(window).height();              // Used to randomize Y-Pos 
var maxSize = 50;                           // Maximal Particle Size
var minSize = 10;                           // Minimum Particle Size
var showProx = "yes";                       // Show Proximity Radius around Cursor
var partBGC = "random";                     // Particle Background-Color (Can be Randomized with: "random")
var partBGCT = 0.25;                        // Particle Background-Color Transparency (0 - 1)
var partBW = "1px";                         // Particle Border Width
var partBS = "solid";                       // Particle Border Style
var partBC = "rgba(255,255,255,0.5)";       // Particle Border Color
var animDur = 5;                            // Animation Duration in ms (5-15 is best)
var partShape = "circle";                   // Choose Shape (square, circle, or px... its just a border-radius)

// All Colors in the Settings are CSS-Based
// (Accepting Hex, RGB, RGBA, or just Color-Value e.g."red")




// Create Particles & Randomize them
$(document).ready(function () {
    $("#welcome").delay(3000).hide(300);
    for (i = 0; i < particles; i++) {
        $("#canvas").append(`<div class="part part${i}"></div>`);
        var ranX = Math.floor(Math.random() * winW) + 1;
        var ranY = Math.floor(Math.random() * winH) + 1;
        var ranSize = Math.floor(Math.random() * maxSize) + minSize;
        $(".part" + i).css("top", ranY);
        $(".part" + i).css("left", ranX);
        $(".part" + i).css("height", ranSize);
        $(".part" + i).css("width", ranSize);
    }

    // Colorize Particles
    if (partBGC == "random") {
        for (k = 0; k < particles; k++) {
            var R = Math.floor(Math.random() * 255) + 1;
            var G = Math.floor(Math.random() * 255) + 1;
            var B = Math.floor(Math.random() * 255) + 1;
            $(".part" + k).css("background-color", `rgba(${R},${G},${B},${partBGCT}` + ")");
        }
    } else {
        $(".part").css({ "background-color": `${partBGC}`, "opacity": `${partBGCT}` });
    }

    // Particle Shape
    if (partShape == "square") {
        $(".part").css({ "border-radius": "0%" });
    } else if (partShape == "circle") {
        $(".part").css({ "border-radius": "100%" });
    } else {
        $(".part").css({ "border-radius": `${partShape}` });
    }

    // Particle Border
    $(".part").css('border', `${partBW} ${partBS} ${partBC}`);
});

// Pull & Push Handling
pull_or_push = "push";

$(document).on("mousedown", function () {
    pull_or_push = "pull";
    op1 = "-";
    op2 = "+";
    op3 = "+";
    op4 = "+";
    doSomething();
});

$(document).on("mouseup", function () {
    pull_or_push = "push";
    op1 = "+";
    op2 = "-";
    op3 = "-";
    op4 = "-";
    cancelAnimationFrame(request)
});

function doSomething(dt) {
    pull_or_push = "pull";
    request = requestAnimationFrame(doSomething)
}

if (pull_or_push == "push") {
    op1 = "+";
    op2 = "-";
    op3 = "-";
    op4 = "-";
} else {
    op1 = "-";
    op2 = "+";
    op3 = "+";
    op4 = "+";
}

// Handling for Showing Cursor Radius
if (showProx == "yes") {
    var sPs = "#proximity";
    var sPs2 = "#proximity2";
    var sPs3 = "#proximity3";
} else {
    var sPs = "";
    var sPs2 = "";
    var sPs3 = "";
}

// Main Function
jQuery(function ($) {
    // var currentMousePos = { x: -1, y: -1 };

    // Mousemove Event
    $(document).mousemove(function (event) {

        // currentMousePos.x = event.pageX;
        // currentMousePos.y = event.pageY;
        // var coords = "X coords: " + currentMousePos.x + ", Y coords: " + currentMousePos.y;
        // document.getElementById("output").innerHTML = coords;

        // Particle Animation Function
        function partAnim(particle) {

            // Variables for Positions
            var wi = particle.width();
            var he = particle.height();
            var off = particle.offset();
            var off_l = off.left;
            var off_t = off.top;
            var posX = event.pageX;
            var posY = event.pageY;
            var p1 = {
                x: off_l + wi / 2,
                y: off_t + he / 2
            };
            var p2 = {
                x: posX,
                y: posY
            };

            // Proximity Radius around Cursor
            $(sPs).css({
                'width': prox * 2,
                'height': prox * 2,
                'left': posX,
                'top': posY
            });
            $(sPs2).css({
                'width': prox2 * 2,
                'height': prox2 * 2,
                'left': posX,
                'top': posY
            });
            $(sPs3).css({
                'width': prox3 * 2,
                'height': prox3 * 2,
                'left': posX,
                'top': posY
            });

            // angle in radians
            var rad = Math.atan2(p2.y - p1.y, p2.x - p1.x);
            var stepSize = 1;

            // If Particle in inner Circle
            if (
                posX + prox > off_l &&
                posX - prox < off_l + wi &&
                posY + prox > off_t &&
                posY - prox < off_t + he
            ) {
                if (rad < 0) {
                    var sX = (stepSize + rad) * psm1;
                    var sY = stepSize * psm1;
                    particle.animate(
                        { top: `${op1}=${sY}px`, left: `${op2}=${sX}px` },
                        animDur
                    );
                } else {
                    var sX = (stepSize - rad) * psm1;
                    var sY = stepSize * psm1;
                    particle.animate(
                        { top: `${op3}=${sY}px`, left: `${op4}=${sX}px` },
                        animDur
                    );
                }
                // If Particle in middle Circle
            } else if (
                posX + prox2 > off_l &&
                posX - prox2 < off_l + wi &&
                posY + prox2 > off_t &&
                posY - prox2 < off_t + he
            ) {
                if (rad < 0) {
                    var sX = (stepSize + rad) * psm2;
                    var sY = stepSize * psm2;
                    particle.animate(
                        { top: `${op1}=${sY}px`, left: `${op2}=${sX}px` },
                        animDur
                    );
                } else {
                    var sX = (stepSize - rad) * psm2;
                    var sY = stepSize * psm2;
                    particle.animate(
                        { top: `${op3}=${sY}px`, left: `${op4}=${sX}px` },
                        animDur
                    );
                }
                // If Particle in outer Circle
            } else if (
                posX + prox3 > off_l &&
                posX - prox3 < off_l + wi &&
                posY + prox3 > off_t &&
                posY - prox3 < off_t + he
            ) {
                if (rad < 0) {
                    var sX = (stepSize + rad) * psm3;
                    var sY = stepSize * psm3;
                    particle.animate(
                        { top: `${op1}=${sY}px`, left: `${op2}=${sX}px` },
                        animDur
                    );
                } else {
                    var sX = (stepSize - rad) * psm3;
                    var sY = stepSize * psm3;
                    particle.animate(
                        { top: `${op3}=${sY}px`, left: `${op4}=${sX}px` },
                        animDur
                    );
                }
            }
        }
        // Call Particle Animation Function for each Particle
        for (j = 0; j < particles; j++) {
            var particle = $(".part" + j);
            partAnim(particle);
        }
    });
});

External CSS

  1. https://codepen.io/Tibixx/pen/rZzrwG.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js
  2. https://codepen.io/Tibixx/pen/rZzrwG.js