🐝 💣 follow one

In this example below you will see how to do a 🐝 💣 follow one with some HTML / CSS and Javascript

Follow one animation - Click to pause animation. Inspiration from https://twitter.com/beesandbombs/status/1001598288326471680

Thumbnail
This awesome code was written by kunukn, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright kunukn ©
  • HTML
  • CSS
  • JavaScript
    <div class='js scene'>  
  <div class='transform'>  
    - for c in (1..3)
      <div class="js container container--#{c}">
        <div class="group group--1 ">
          - for i in (1..(9*5))
            <div class = 'box box--#{i}'><i></i></div>
        </div>
        <div class="group group--2 ">
          - for i in (1..(10*6))
            <div class = 'box box--#{i}'><i></i></div>
        </div>
      </div>
  </div>
</div>

<a class="reference" href="https://twitter.com/beesandbombs/status/1001598288326471680" target="_blank">inspiration</a>

/*Downloaded from https://www.codeseek.co/kunukn/andx1f41d-andx1f4a3-follow-one-aKdRKq */
    // https://video.twimg.com/tweet_video/DeZkNZpXUAAdX5k.mp4
// https://twitter.com/beesandbombs/status/1001598288326471680

@import "compass"; // enable cos and sin functions

$ease: cubic-bezier(0.645, 0.045, 0.355, 1);
$anim: anim-todo 3s $ease infinite;

$background-color: #151315;
$colors: #ff5339, #006edd, #21ae3e;
$size: 1rem; // circle size

// color group dist
$group-dist: $size*1.6;

$x: $size * 5; // dist in x
$y: 2 * sin(60deg) * $x; // dist in y

$ystart: 0; // start from this y in animation

$dimension1: 9, 5; // same as in html
$dimension2: 10, 6;

$top: 0, sin(-60deg) * $group-dist, sin(0deg) * $group-dist;
$left: 0, cos(-60deg) * $group-dist, cos(0deg) * $group-dist;

html {
  font-size: 6px;
  @media (min-width: 500px) {
    font-size: 8px;
  }
  @media (min-width: 800px) {
    font-size: 9px;
  }
  @media (min-width: 1100px) {
    font-size: 12px;
  }
}

body {
  font-family: sans-serif;
  margin: 0;
  display: flex;
  justify-content: centeR;
  align-items: center;
  background: $background-color;
  overflow: hidden;
  position: relative;
  width: 100vw;
  height: 100vh;
}

.scene {
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  cursor: pointer;

  &.animate {
    .container--1 .box > i {
      animation-name: anim-1;
    }
    .container--2 .box > i {
      animation-name: anim-2;
    }
    .container--3 .box > i {
      animation-name: anim-3;
    }
  }
  &.paused {
    .container--1 .box > i {
      animation-play-state: paused;
    }
    .container--2 .box > i {
      animation-play-state: paused;
    }
    .container--3 .box > i {
      animation-play-state: paused;
    }
  }
}

.transform {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: translateY($y/4);
}

.container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  &--1 {
    color: nth($colors, 1);
    top: nth($top, 1);
    left: nth($left, 1);
  }
  &--2 {
    color: nth($colors, 2);
    top: nth($top, 2);
    left: nth($left, 2);
  }
  &--3 {
    color: nth($colors, 3);
    top: nth($top, 3);
    left: nth($left, 3);
  }
}

.group {
  position: absolute;
  //outline: 1px solid pink;
  display: flex;
  flex-wrap: wrap;

  &--1 {
    $width: nth($dimension1, 1) * $x;
    $height: nth($dimension1, 2) * $y;
    width: $width;
    height: $height;
    top: calc(50% - #{$height/2});
    left: calc(50% - #{$width/2});
  }
  &--2 {
    $width: nth($dimension2, 1) * $x;
    $height: nth($dimension2, 2) * $y;
    width: $width;
    height: $height;
    top: calc(50% - #{$height/2});
    left: calc(50% - #{$width/2});
    //outline: 1px solid pink;
  }
}

.box {
  width: $x;
  height: $y;
  display: flex;
  justify-content: center;
  align-items: center;
  //outline: 1px solid white;

  > i {
    transform: translateY(0) translateZ(0);

    animation: $anim;
    font-style: normal;
    display: block;
    position: relative;
    top: 0;
    left: 0;
    width: $size;
    height: $size;
    border-radius: 50%;
    background: currentColor;
    &.center {
      // box-shadow: 0 0 0 1px #eee;
    }
  }
}

@keyframes anim-1 {
  $from: 0;
  $to: -$y/2;
  0%,
  100% {
    transform: translateY(0);
  }
  25% {
    transform: translateY($to);
  }
  50% {
    transform: translateY($to);
  }
  75% {
    transform: translateY(0);
  }
}
@keyframes anim-2 {
  $xto: $x/2 - cos(60deg) * $group-dist + cos(0deg) * $group-dist;
  $yto: sin(60deg) * $group-dist;

  0%,
  100% {
    transform: translateX(0) translateY(0);
  }
  25% {
    transform: translateX($xto) translateY($yto);
  }
  50% {
    transform: translateX($xto) translateY($yto);
  }
  75% {
    transform: translateX(0) translateY(0);
  }
}
@keyframes anim-3 {
  $xto: -$x/2 - cos(60deg) * $group-dist;
  $yto: sin(60deg) * $group-dist;

  0%,
  100% {
    transform: translateX(0) translateY(0);
  }
  25% {
    transform: translateX($xto) translateY($yto);
  }
  50% {
    transform: translateX($xto) translateY($yto);
  }
  75% {
    transform: translateX(0) translateY(0);
  }
}

@keyframes rotate{
  to{
    transform: rotate(1turn);
  }
}

.reference {
  position: fixed;
  bottom: 2px;
  right: 2px;
  color: #5f5f5f;
  font-size: 14px;
  padding: 2px;
  transition: 280ms;
  border-radius: 2px;
  &:hover {
    background: rgba(white, 0.1);
  }
}



/*Downloaded from https://www.codeseek.co/kunukn/andx1f41d-andx1f4a3-follow-one-aKdRKq */
    polyfill();
const log = console.log;
const distance = (x0, y0, x1, y1) => Math.hypot(x1 - x0, y1 - y0);
const scene = qs(".js.scene");
const maxAnimationDelay = 700;

setup();
run();

function setup() {
  
  let getCenter = container => {
    let dotsgroup1 = qsa(".group--1 .box > i", container);
    return dotsgroup1[Math.floor(dotsgroup1.length / 2)];
  };
  
  let calcAndApply = index => {
    let container = qs(".js.container--" + index);  
    let dots = qsa(".box > i", container);
    let center = getCenter(container);
    center.classList.add("center");
    let centerRect = center.getBoundingClientRect();
    applyAnimDelay(centerRect, dots)
  }
  
  calcAndApply(1);
  calcAndApply(2);
  calcAndApply(3);
  
  scene.addEventListener("click", onClick);
}

function onClick(event) {
  scene.classList.toggle("paused");
}

function run() {
  setTimeout(() => scene.classList.add("animate"), 500);
}

function applyAnimDelay(centerRect, dots) {
  let dists = [];
  dots.forEach(c => {
    let rect = c.getBoundingClientRect();
    let dist = distance(centerRect.x, centerRect.y, rect.x, rect.y);
    dist = Math.round(dist * 100) / 100;
    dists.push({ el: c, dist });
  });

  //dists.sort( (a,b) => a.dist - b.dist);
  //let toHide = dists.slice(dists.length- 4); // last n items
  //toHide.forEach(i => i.el.style.display = 'none');
  
  const max = Math.max(...dists.map(d => d.dist));
  
  dists.forEach(d => {
    let delay = Math.round(rangeMap(d.dist, 0, max, 0, maxAnimationDelay));
    d.el.style.animationDelay = `${delay}ms`;
  });
}

function qs(expr, context) {
  return (context || document).querySelector(expr);
}
function qsa(expr, context) {
  return [].slice.call((context || document).querySelectorAll(expr), 0);
}

function rangeMap(x, a, b, c, d) {
  if (a === b) return c;
  if (c === d) return c;
  return (x - a) / (b - a) * (d - c) + c;
}

function polyfill() {
  Math.hypot =
    Math.hypot ||
    function(x, y) {
      // https://bugzilla.mozilla.org/show_bug.cgi?id=896264#c28
      var max = 0;
      var s = 0;
      for (var i = 0; i < arguments.length; i += 1) {
        var arg = Math.abs(Number(arguments[i]));
        if (arg > max) {
          s *= max / arg * (max / arg);
          max = arg;
        }
        s += arg === 0 && max === 0 ? 0 : arg / max * (arg / max);
      }
      return max === 1 / 0 ? 1 / 0 : max * Math.sqrt(s);
    };
}


Comments