<div class="dot"></div>
<div class="container">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
</div>
body, html {
  width: 100%;
  height: 100%;
  background-color: #1E1B16;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.container {
  width: 140vmin;
  height: 90vmin;
  margin: 5vmin;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}

.dot {
  position: fixed;
  width: 6vmin;
  height: 6vmin;
  margin-top: 0vmin;
  margin-bottom: 0vmin;
  margin-left: 0vmin;
  background-color: #FFBB00;
  border-radius: 50%;
  z-index: 2;
  box-shadow: 0 0 5px #FFBB00, 0 0 20px 10px rgba(255, 187, 0, 0.3);
}

.box {
  background-color: #423F3B;
  width: 10vmin;
  height: 10vmin;
  margin: 2.5vmin;
  border-radius: 16%;
  box-shadow: 0 0 10px rgba(66, 63, 59, 0.5);
}
const boxes = [...document.querySelectorAll('.box')];
const dot = document.querySelector('.dot');
const container = document.querySelector('.container');
const rect = container.getBoundingClientRect();
const coords = {
  x: [0, Math.round(rect.width / 4), Math.round(3 * rect.width / 4), rect.width],
  y: [0, Math.round(rect.height / 2), rect.height]
};
const pos = {x: coords.x[0] + rect.left, y: coords.y[0] + rect.top};

// Move the dot to the given coordinates, rotating
// all the boxes so that they are facing the given coordinates
const moveDot = (x, y) => {
  // Position the dot
  dot.style.top = `${y}px`;
  dot.style.left = `${x}px`;
  pos.x = x;
  pos.y = y;
  
  // Rotate all the boxes
  boxes.forEach(box => {
    const {top, left, width, height} = box.getBoundingClientRect();
    const adjacent = x - left - width / 2;
    const opposite = y - top - height / 2;
    
    // arctan gives us the degree based on the opposite & adjacent edges
    // of the triangle created between the box' center and the given
    // coordinates
    const radians = Math.atan(opposite / adjacent); 
    box.style.transform = `rotate(${radians}rad)`;
  });
};

const generateArray = length => [...new Array(length)].map((_, i) => i);
const random = arr => arr[Math.floor(Math.random() * arr.length)];

let animation;
let coordinate = 'x';
const prev = {x: 0, y: 0};

// Recursively animate the dot the a random set of coordinates
const animate = () => {
  const pool = generateArray(coords[coordinate].length);
  pool.splice(prev[coordinate], 1);
  const next = random(pool);
  prev[coordinate] = next;
  
  animation = TweenMax.to(pos, 1.8, {
    [coordinate]: coords[coordinate][next] + rect[coordinate],
    ease: Power2.easeInOut, 
    onUpdate: function() {
      moveDot(pos.x, pos.y);
    },
    onComplete: animate,
  });
  // Toggle the animated coordinate (animate a differen axis every time)
  coordinate = coordinate === 'x' ? 'y' : 'x';
}
animate();
const dAnimate = _.debounce(animate, 1000);

// Stop animation on mouse move and follow the cursor until 
// it rests for 500ms, at which point the animation should
// start again
window.addEventListener('mousemove', ({x, y}) => {
  animation.kill();
  dAnimate();
  window.requestAnimationFrame(() => {
    moveDot(x, y);
  });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.core.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js