<div class="explosion-container">
  <span class="explosion-text">點擊這裡!</span>
</div>
body {
  height: 90vh;
  background: #282c34;
  font-family: Arial, sans-serif;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.explosion-container {
  display: inline-block;
  font-size: 40px;
  cursor: pointer;
  user-select: none;
  position: relative;
}
.explosion-text {
  display: inline-block;
  position: relative;
}

.explosion-text span {
  display: inline-block;
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  transition: transform 0.6s ease-out, opacity 0.6s ease-out;
}

.explosion-text span.exploded {
  opacity: 1;
  transform: translate(calc(var(--x) * 1000px), calc(var(--y) * 1000px))
    rotate(calc(var(--angle) * 360deg)) scale(0);
}
document
  .querySelector(".explosion-text")
  .addEventListener("click", function () {
    const text = this.textContent;
    this.innerHTML = "";

    // Create spans for each character
    for (let i = 0; i < text.length; i++) {
      const span = document.createElement("span");
      span.textContent = text[i];
      span.style.setProperty("--x", Math.random() - 0.5);
      span.style.setProperty("--y", Math.random() - 0.5);
      span.style.setProperty("--angle", Math.random());
      this.appendChild(span);
    }

    requestAnimationFrame(() => {
      this.querySelectorAll("span").forEach((span) => {
        span.classList.add("exploded");
      });
    });

    // Add reverting class after 3 seconds
    setTimeout(() => {
      this.classList.add("reverting");

      setTimeout(() => {
        // Clean up the reverting state
        this.classList.remove("reverting");
        this.innerHTML = text; // Restore original text
      }, 600); // Match the duration of the transition
    }, 1000); // 1 seconds delay
  });

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.