<div id="dots">
    <div id="mouse"></div>
</div>
body
    margin: 0
    padding: 0
    width: 100%
    height: 100vh
    background: #000

#dots
    position: relative
    overflow: hidden
    height: 100%
    width: 100%

    .dot
        position: absolute
        transition: 1s cubic-bezier(0, 0, 0.58, 1)
        display: flex
        justify-content: center
        align-items: center

        > .circle
            position: absolute
            border-radius: 100px

        > .line
            height: 100px
            width: 1px
            position: absolute
            background: #fff
            transform-origin: 0 0 0
            top: 0
            left: 0
            transition: 1s cubic-bezier(0, 0, 0.58, 1)

    #mouse
        position: absolute
        width: 100%
        height: 100%
        z-index: 10
View Compiled
$(() => {
    dots($('#dots'), arrDots);
})

var arrDots = [
    {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: [1]
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }, {
        radius: rnd(10, 20),
        blur: rnd(0, 9),
        y: rnd(10, $(window).height()),
        x: rnd(10, $(window).width()),
        lineTo: []
    }
]

function dots(container, arrDots) {
    var linesTo = [];

    arrDots.forEach((item) => {
        container.append($('<div>', {
            css: {
                top: item.y,
                left: item.x
            }
        }).addClass('dot').append($('<div>', {
            css: {
                width: item.radius,
                height: item.radius,
                'background': 'radial-gradient(rgb(255, 255, 255), rgba(255, 255, 255, .' + item.blur + ') 50%)'
            }
        }).addClass('circle')));

        item.lineTo.forEach((el) => {
            linesTo.push(el);

            container.children().last().append($('<div>', {
                css: drawLine(item, arrDots[el])
            }).addClass('line').data('lineTo', el));
        })
    })

    linesTo.forEach((item) => {
        updateByMutation($('.dot').eq(item).get(0), item);
    })

    container.find('#mouse').mousemove((e) => {
        container.find('.dot').each(function() {
            var posY = parseInt($(this).css('top')),
                posX = parseInt($(this).css('left')),
                l = Math.pow((Math.pow(posY - e.pageY, 2) + Math.pow(posX - e.pageX, 2)), 1 / 5) * 2,
                direction, offsetY, offsetX;

            direction = Math.atan2(posY - e.pageY, posX - e.pageX)

            offsetY = -Math.cos(direction) * l;
            offsetX = -Math.sin(direction) * l;

            $(this).css({
                'margin-top': offsetX + 'px',
                'margin-left': offsetY + 'px'
            });
        })
    })

    container.find('#mouse').mouseout((e) => {
        /*container.find('.dot').each(function() {
            $(this).css({
                'margin-top': '',
                'margin-left': ''
            })
        })*/
    })

    function drawLine(point1, point2) {
        return {
            transform: 'rotate(' + (Math.atan2(point1.y - point2.y, point1.x - point2.x) + (Math.PI / 2)) + 'rad)',
            height: Math.sqrt((Math.pow(point1.y - point2.y, 2) + Math.pow(point1.x - point2.x, 2)))
        };
    }

    function updateByMutation(target, id) {
        const config = {
            attributes: true
        }, callback = function() {
            $('.dot .line').each(function() {
                console.log(parseFloat($(target).css('left')), parseFloat($(target).css('margin-left').replace('px', '')));

                if ($(this).data('lineTo') == id)
                    $(this).css(drawLine({
                        x: $(this).parent().offset().left,
                        y: $(this).parent().offset().top
                    }, {
                        x: parseFloat($(target).css('left')) + parseFloat($(target).css('margin-left').replace('px', '')),
                        y: parseFloat($(target).css('top')) + parseFloat($(target).css('margin-top').replace('px', ''))
                    }))
            })        
        }, observer = new MutationObserver(callback);
    
        observer.observe(target, config);
    }
}

function rnd(min, max) {
    let rnd = min + Math.random() * (max + 1 - min);
    return Math.floor(rnd);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js