<div id="heart-1" class="heart heart--1"></div>
<div id="heart-2" class="heart heart--2"></div>
/* The parts of the css that affect the movement */
.heart {
            position: absolute;
            transition: ease 500ms; /* This value must be kept in time with the loopFrequency below */
            transition-property: left, top, color;
        }

/* The pretty! */
.heart {
  background-color: red;
  display: inline-block;
  height: 40px;
  top: 0;
  width: 40px;
  transform: rotate(-45deg);
}

.heart:before,
.heart:after {
  content: "";
  background-color: red;
  border-radius: 50%;
  height: 100%;
  position: absolute;
  width: 100%;
}

.heart:before {
  top: -50%;
  left: 0;
}

.heart:after {
  left: 50%;
  top: 0;
}
document.addEventListener("DOMContentLoaded", hearts);

        function hearts(){
            // Some variables we'll use in the code below
            var loopFrequency = 500;
            var loopsTotal = 0; 

            var maxX;
            var maxY;
            var maxMovementDistance;

            var heartsTimeout;
            /** @type {HTMLElement} */
            var heartOne;
            /** @type {HTMLElement} */
            var heartTwo;

            init();
            // A nice place to set all our code that needs to run once
            function init(){


                // Figure out how bit big the stage is
                maxX = window.innerWidth;
                maxY = window.innerHeight;
                maxMovementDistance = maxX * 0.04;

                // Figure out how big our hearts should be when the page loads
                // The smaller height or width, and 25% of that
                var heartSize = Math.min(window.innerWidth, window.innerHeight) * .25 + 'px';

                // Get our elements on the screen to play with
                heartOne = document.getElementById('heart-1');
                heartTwo = document.getElementById('heart-2');

                // Put heart one in a random spot on the screen
                heartOne.style.left = Math.round(maxX / 2) + 'px';
                heartOne.style.top = Math.round(maxY / 2) + 'px';
                heartOne.style.width = heartSize;
                heartOne.style.height = heartSize;

                // Put heart two in a random spot on the screen
                heartTwo.style.left = Math.round(maxX / 2) + 'px';
                heartTwo.style.top = Math.round(maxY / 2) + 'px';
                heartTwo.style.width = heartSize;
                heartTwo.style.height = heartSize;

                // Start the show!
                loop();

                // Start looking for the position of the cursor
                document.addEventListener("mousemove", mouseMovement);
            }

            /**
             * @param {Event} event
             */
            function mouseMovement(event){
                styleHeartByProximity(heartOne, event.clientX, event.clientY);
                styleHeartByProximity(heartTwo, event.clientX, event.clientY);
            }

            /**
             * @param {HTMLElement} heart
             * @param x
             * @param y
             */
            function styleHeartByProximity(heart, x, y){
                // How close are we?
                var xDistance = heart.offsetLeft - x;
                var yDistance = heart.offsetTop - y;

                // Negative distance still counts as distance!
                // Use Math.abs to change negative values into positive
                xDistance = Math.abs(xDistance);
                yDistance = Math.abs(yDistance);

                var totalDistance = xDistance + yDistance;

                // Make the hearts smaller by some percent
                var sizePercent = totalDistance / Math.max( maxX, maxY );
                // Make sure it is never outside of the 0 - 100 range
                // Keep it less than 100%
                sizePercent = Math.min( 1, sizePercent );
                // Keep it more than 2% (or we can't see it)
                sizePercent = Math.max( 0.02, sizePercent );

                var transformCss = 'scale(' + sizePercent +') rotate(-45deg)';
                heart.style.transform = transformCss;
            }

            // The main guts of the program
            function loop(){
                moveHeart(heartOne);
                moveHeart(heartTwo);

                // Increase the number of times we've done it
                ++loopsTotal;
                // If it's more than 500, let's take a break
                // This prevents the browser from getting stuck
                if( loopsTotal > 500 ){
                    return;
                }
                // Let's do it again, in a little bit of time
                heartsTimeout = setTimeout(loop, loopFrequency);
            }

            /**
             * Moves a single heart
             * @param {HTMLElement} heart
             */
            function moveHeart(heart){
                // Get the current positions
                var currentLeftStyle = heart.style.left;
                var currentTopStyle = heart.style.top;

                // The 'Styles' come with measurements of distance attached like 'px', 'em', or 'vh'
                // We can't use those for math! Take those off
                //    These are regular expressions, they let us replace 'patterns' in text
                //    Here were are replacing 'Anything that is a,b,c,d through z' with "" (nothing)
                //    It's like "Find and replace" but more powerful
                var currentLeft = currentLeftStyle.replace(/[a-zA-Z]+/, '');
                var currentTop = currentTopStyle.replace(/[a-zA-Z]+/, '');

                // The numbers we got aren't real numbers!
                // Because they started as strings, we need to make sure the system treats them as numbers instead
                var currentLeft = parseFloat(currentLeft);
                var currentTop = parseFloat(currentTop);

                var addToLeft = getMovement();
                var addToTop = getMovement();

                var left = currentLeft + addToLeft;
                var top = currentTop + addToTop;

                // There's a chance the numbers we got are more than our maximum and minimum
                // Let's make sure they never go past the edge
                left = stayInScreen(left, maxX);
                top = stayInScreen(top, maxY);

                // Update the actual position of the heart!
                heart.style.left = left + 'px';
                heart.style.top = top + 'px';
            }

            function getMovement(){
                // Get some random distance, within our allowed max distance
                var movement = Math.random() * maxMovementDistance;
                // Let it be positive or negative randomly so the movement isn't easy to guess
                if( Math.random() < 0.5 ){
                    movement *= -1;
                }
                return movement;
            }

            // Keeps the position inside the max and min
            function stayInScreen(position, max) {
                // You could also try Math.min() and Math.max() functions!
                if( position < 0 ){
                    position = 0;
                }
                if( position > max ){
                    position = max;
                }
                return position;
            }
        }
Rerun