JSFiddle - React, Tailwind, and code Playground

by HDL52

HTML

<div class="g-emoji">
    <div class="g-foo"></div>
    <div class="g-bar"></div>
    <div class="g-baz"></div>
</div>

CSS

.g-emoji {
  position: relative;
  width: 200px;
  height: 200px;
  perspective: 2000px;
  transform-style: preserve-3d;
  font-size: 200px;
  animation: rotate 2s alternate infinite ease-in-out, fall .6s alternate infinite cubic-bezier(.22, .16, .04, .99) forwards;


  &::before,
  &::after {
    content: var(--emoji, "\1F600");
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 200px;
    height: 200px;
  }

  &::after {
    transform: translate(-50%, -50%) translateZ(-4px);
  }

  .g-foo,
  .g-bar,
  .g-baz {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
  }

  .g-foo::before,
  .g-foo::after,
  .g-bar::before,
  .g-bar::after,
  .g-baz::before,
  .g-baz::after {
    content: var(--emoji, "\1F600");
    position: absolute;
    top: 50%;
    left: 50%;
    width: 200px;
    height: 200px;
  }

  .g-foo::before {
    transform: translate(-50%, -50%) translateZ(-8px);
    opacity: .95;
  }

  .g-foo::after {
    transform: translate(-50%, -50%) translateZ(-12px);
    opacity: .9;
  }

  .g-bar::before {
    transform: translate(-50%, -50%) translateZ(-16px);
    opacity: .85;
  }

  .g-bar::after {
    transform: translate(-50%, -50%) translateZ(-20px);
    opacity: .8;
  }

  .g-baz::before {
    transform: translate(-50%, -50%) translateZ(-24px);
    opacity: .75;
  }

  .g-baz::after {
    transform: translate(-50%, -50%) translateZ(-28px);
    opacity: .7;
  }
}

@keyframes rotate {
  0% {
    transform: rotateY(-45deg);
  }

  100% {
    transform: rotateY(45deg);
  }
}

@keyframes fall {
  0% {
    scale: 1.25 0.75;
    translate: 0 150px;
  }

  25% {
    scale: 1 1;
  }

  100% {
    scale: 1 1;
    translate: 0 0;
  }
}

JavaScript

// https://www.cnblogs.com/coco1s/p/17595727.html

const emoji = document.querySelectorAll('.g-emoji')[0];

let curTranslate = 0;
let lastTranslate = 0;
let diff = 0;

function aniFun() {
  curTranslate = window.getComputedStyle(emoji, null).getPropertyValue("translate").split(' ')[1].slice(0, -2) - 0;

  // 翻转
  if (diff > 0 && (curTranslate - lastTranslate < 0)) {
    emoji.style = `--emoji: "${generateRandomEmoji()}"`;
  }

  window.requestAnimationFrame(aniFun);
  diff = curTranslate - lastTranslate;
  lastTranslate = curTranslate;
}

function generateRandomEmoji() {
  // 开始的 Emoji 编码
  var emojiStart = 0x1F600;
  var emojiStart2 = 0x1F900;
  // 结束的 Emoji 编码
  var emojiEnd = 0x1F64F;
  var emojiEnd2 = 0x1F9FF;

  var randomCode = Math.random() > 0.5 ?
    Math.floor(Math.random() * (emojiEnd - emojiStart + 1)) + emojiStart :
    Math.floor(Math.random() * (emojiEnd2 - emojiStart2 + 1)) + emojiStart2;
  var emoji = String.fromCodePoint(randomCode);

  return emoji;
}

window.requestAnimationFrame(aniFun);