遇事不决,抛一下(一个好玩的东西)

简介: 遇事不决,抛一下(一个好玩的东西)

html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./css/style.css">
    <title>抛硬币</title>
  </head>
  <body>
    <button class="tip-button">
      <span class="tip-button__text">遇事不决,抛一下</span>
      <div class="coin-wrapper">
        <div class="coin" style="
            --coin-y-multiplier: 0;
            --coin-x-multiplier: 0;
            --coin-scale-multiplier: 0;
            --coin-rotation-multiplier: 0;
            --front-scale-multiplier: 1;
            --front-y-multiplier: -4.898587196589413e-16;
            --middle-scale-multiplier: 1;
            --middle-y-multiplier: 6.123233995736766e-17;
            --back-scale-multiplier: 0;
            --back-y-multiplier: 3.6739403974420594e-16;
            --shine-opacity-multiplier: 0.4;
            --shine-bg-multiplier: 50%;
            opacity: 1;
            ">
          <div class="coin__middle"></div>
          <div class="coin__back"></div>
          <div class="coin__front"></div>
        </div>
      </div>
    </button>
    <script src="./js/script.js"></script>
  </body>
</html>

css

.tip-button {
  background: none;
  border: 0;
  /* border-radius: 0.25rem 0.25rem 0 0; */
  cursor: pointer;
  font-family: "Quicksand", sans-serif;
  font-size: 0.75rem;
  font-weight: 600;
  height: 2.6rem;
  margin-bottom: -4rem;
  outline: 0;
  position: relative;
  top: 0;
  transform-origin: 0% 100%;
  transition: transform 50ms ease-in-out;
  width: 9.5rem;
  -webkit-tap-highlight-color: transparent;
}
/* 按钮滚动 */
.tip-button:active {
  transform: rotate(4deg);
}
.tip-button.clicked {
  animation: 150ms ease-in-out 1 shake;
  pointer-events: none;
}
.tip-button.clicked .tip-button__text {
  opacity: 0;
  transition: opacity 100ms linear 200ms;
}
.tip-button.clicked::before {
  height: 0.5rem;
  width: 60%;
}
.tip-button.clicked .coin {
  transition: margin-bottom 1s linear 200ms;
  margin-bottom: 0;
}
.tip-button.shrink-landing::before {
  transition: width 200ms ease-in;
  width: 0;
}
.tip-button.coin-landed::after {
  opacity: 1;
  transform: scale(1);
  transform-origin: 50% 100%;
}
.tip-button.coin-landed .coin-wrapper {
  background: radial-gradient(circle at 35% 97%,
      rgba(3, 16, 50, 0.4) 0.04rem,
      transparent 0.04rem),
    radial-gradient(circle at 45% 92%,
      rgba(3, 16, 50, 0.4) 0.04rem,
      transparent 0.02rem),
    radial-gradient(circle at 55% 98%,
      rgba(3, 16, 50, 0.4) 0.04rem,
      transparent 0.04rem),
    radial-gradient(circle at 65% 96%,
      rgba(3, 16, 50, 0.4) 0.06rem,
      transparent 0.06rem);
  background-position: center bottom;
  background-size: 100%;
  bottom: -1rem;
  opacity: 0;
  transform: scale(2) translateY(-10px);
}
.tip-button__text {
  color: #fff;
  margin-right: 1.8rem;
  opacity: 1;
  position: relative;
  transition: opacity 100ms linear 500ms;
  z-index: 3;
}
.tip-button::before {
  background: #031032;
  border-radius: 0.25rem;
  bottom: 0;
  content: "";
  display: block;
  height: 100%;
  left: 50%;
  position: absolute;
  transform: translateX(-50%);
  transition: height 250ms ease-in-out 400ms, width 250ms ease-in-out 300ms;
  width: 100%;
  z-index: 2;
}
.tip-button::after {
  bottom: -1rem;
  color: #031032;
  content: attr(content);
  height: 110%;
  left: 0;
  opacity: 0;
  position: absolute;
  pointer-events: none;
  text-align: center;
  transform: scale(0);
  transform-origin: 50% 20%;
  transition: transform 200ms cubic-bezier(0, 0, 0.35, 1.43);
  width: 100%;
  z-index: 1;
}
.coin-wrapper {
  background: none;
  bottom: 0;
  height: 18rem;
  left: 0;
  opacity: 1;
  overflow: hidden;
  pointer-events: none;
  position: absolute;
  transform: none;
  transform-origin: 50% 100%;
  transition: opacity 200ms linear 100ms, transform 300ms ease-out;
  width: 100%;
}
.coin {
  --front-y-multiplier: 0;
  --back-y-multiplier: 0;
  --coin-y-multiplier: 0;
  --coin-x-multiplier: 0;
  --coin-scale-multiplier: 0;
  --coin-rotation-multiplier: 0;
  --shine-opacity-multiplier: 0.4;
  --shine-bg-multiplier: 50%;
  bottom: calc(var(--coin-y-multiplier) * 1rem - 3.5rem);
  height: 3.5rem;
  margin-bottom: 3.05rem;
  position: absolute;
  right: calc(var(--coin-x-multiplier) * 34% + 16%);
  transform: translateX(50%) scale(calc(0.4 + var(--coin-scale-multiplier))) rotate(calc(var(--coin-rotation-multiplier) * -1deg));
  transition: opacity 100ms linear 200ms;
  width: 3.5rem;
  z-index: 3;
}
.coin__front,
.coin__middle,
.coin__back,
.coin::before,
.coin__front::after,
.coin__back::after {
  border-radius: 50%;
  box-sizing: border-box;
  height: 100%;
  left: 0;
  position: absolute;
  width: 100%;
  z-index: 3;
}
.coin__front {
  background: radial-gradient(circle at 50% 50%,
      transparent 50%,
      rgba(115, 124, 153, 0.4) 54%,
      #c2cadf 54%),
    linear-gradient(210deg, #8590b3 32%, transparent 32%),
    linear-gradient(150deg, #8590b3 32%, transparent 32%),
    linear-gradient(to right,
      #8590b3 22%,
      transparent 22%,
      transparent 78%,
      #8590b3 78%),
    linear-gradient(to bottom,
      #fcfaf9 44%,
      transparent 44%,
      transparent 65%,
      #fcfaf9 65%,
      #fcfaf9 71%,
      #8590b3 71%),
    linear-gradient(to right,
      transparent 28%,
      #fcfaf9 28%,
      #fcfaf9 34%,
      #8590b3 34%,
      #8590b3 40%,
      #fcfaf9 40%,
      #fcfaf9 47%,
      #8590b3 47%,
      #8590b3 53%,
      #fcfaf9 53%,
      #fcfaf9 60%,
      #8590b3 60%,
      #8590b3 66%,
      #fcfaf9 66%,
      #fcfaf9 72%,
      transparent 72%);
  background-color: #8590b3;
  background-size: 100% 100%;
  transform: translateY(calc(var(--front-y-multiplier) * 0.3181818182rem / 2)) scaleY(var(--front-scale-multiplier));
}
.coin__front::after {
  background: rgba(0, 0, 0, 0.2);
  content: "";
  opacity: var(--front-y-multiplier);
}
.coin__middle {
  background: #737c99;
  transform: translateY(calc(var(--middle-y-multiplier) * 0.3181818182rem / 2)) scaleY(var(--middle-scale-multiplier));
}
.coin__back {
  background: radial-gradient(circle at 50% 50%,
      transparent 50%,
      rgba(115, 124, 153, 0.4) 54%,
      #c2cadf 54%),
    radial-gradient(circle at 50% 40%, #fcfaf9 23%, transparent 23%),
    radial-gradient(circle at 50% 100%, #fcfaf9 35%, transparent 35%);
  background-color: #8590b3;
  background-size: 100% 100%;
  transform: translateY(calc(var(--back-y-multiplier) * 0.3181818182rem / 2)) scaleY(var(--back-scale-multiplier));
}
.coin__back::after {
  background: rgba(0, 0, 0, 0.2);
  content: "";
  opacity: var(--back-y-multiplier);
}
.coin::before {
  background: radial-gradient(circle at 25% 65%,
      transparent 50%,
      rgba(255, 255, 255, 0.9) 90%),
    linear-gradient(55deg,
      transparent calc(var(--shine-bg-multiplier) + 0%),
      #e9f4ff calc(var(--shine-bg-multiplier) + 0%),
      transparent calc(var(--shine-bg-multiplier) + 50%));
  content: "";
  opacity: var(--shine-opacity-multiplier);
  transform: translateY(calc(var(--middle-y-multiplier) * 0.3181818182rem / -2)) scaleY(var(--middle-scale-multiplier)) rotate(calc(var(--coin-rotation-multiplier) * 1deg));
  z-index: 10;
}
.coin::after {
  background: #737c99;
  content: "";
  height: 0.3181818182rem;
  left: 0;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 100%;
  z-index: 2;
}
@keyframes shake {
  0% {
    transform: rotate(4deg);
  }
  66% {
    transform: rotate(-4deg);
  }
  100% {
    transform: rotate();
  }
}
/********* BODY STYLES *********/
html,
body {
  height: 100%;
}
body {
  align-items: center;
  background: #f4f7ff;
  display: flex;
  justify-content: center;
  -webkit-font-smoothing: antialiased;
}

js

const tipButtons = document.querySelectorAll(".tip-button");
// Loop through all buttons (allows for multiple buttons on page)
//循环浏览所有按钮(允许页面上有多个按钮)
tipButtons.forEach((button) => {
  let coin = button.querySelector(".coin");
  //数字越大,动画越慢
  coin.maxMoveLoopCount = 90;
  // 为button绑定click事件
  button.addEventListener("click", () => {
    const f1 = () => parseInt(Math.random() * 5) + 1;
    // 等概率发生器
    const f2 = () => {
      let c = 0;
      do {
        c = f1();
      } while (c === 3);
      // 1、2 => 0    4、5 => 1
      return c > 3 ? true : false;
    };
    const flag = f2();
    if (flag) {
      button.setAttribute("content", "正面");
    } else {
      button.setAttribute("content", "反面");
    }
    // 如果正在被点击
    if (button.clicked) return;
    // 新增clicked的class
    button.classList.add("clicked");
    // Wait to start flipping th coin because of the button tilt animation
    setTimeout(() => {
      // 定义随机反转的速度
      coin.sideRotationCount = Math.floor(Math.random() * 5) * 90;
      // 最大翻转角度
      coin.maxFlipAngle = (Math.floor(Math.random() * 4) + 3) * Math.PI;
      button.clicked = true;
      flipCoin();
    }, 50);
  });
  const flipCoin = () => {
    coin.moveLoopCount = 0; // 移动循环计数
    flipCoinLoop();
  };
  const flipCoinLoop = () => {
    coin.moveLoopCount++;
    let percentageCompleted = coin.moveLoopCount / coin.maxMoveLoopCount;
    // 获取投掷角度
    coin.angle = -coin.maxFlipAngle * Math.pow(percentageCompleted - 1, 2) +
      coin.maxFlipAngle;
    // Calculate the scale and position of the coin moving through the air
    // 计算硬币在空中移动的比例和位置
    coin.style.setProperty(
      "--coin-y-multiplier",
      -11 * Math.pow(percentageCompleted * 2 - 1, 4) + 11
    );
    coin.style.setProperty("--coin-x-multiplier", percentageCompleted);
    coin.style.setProperty(
      "--coin-scale-multiplier",
      percentageCompleted * 0.6
    );
    coin.style.setProperty(
      "--coin-rotation-multiplier",
      percentageCompleted * coin.sideRotationCount
    );
    // Calculate the scale and position values for the different coin faces
    // The math uses sin/cos wave functions to similate the circular motion of 3D spin
    //计算不同硬币表面的比例和位置值
    //数学使用sin/cos波函数来模拟三维自旋的圆周运动
    // 前面样式
    coin.style.setProperty(
      "--front-scale-multiplier",
      Math.max(Math.cos(coin.angle), 0)
    );
    // console.log("===== : 前面", Math.sin(coin.angle));
    coin.style.setProperty("--front-y-multiplier", Math.sin(coin.angle));
    // 中间样式
    coin.style.setProperty(
      "--middle-scale-multiplier",
      Math.abs(Math.cos(coin.angle), 0)
    );
    coin.style.setProperty(
      "--middle-y-multiplier",
      Math.cos((coin.angle + Math.PI / 2) % Math.PI)
    );
    // 背面样式
    coin.style.setProperty(
      "--back-scale-multiplier",
      Math.max(Math.cos(coin.angle - Math.PI), 0)
    );
    // console.log("===== : 背面", Math.sin(coin.angle - Math.PI));
    coin.style.setProperty(
      "--back-y-multiplier",
      Math.sin(coin.angle - Math.PI)
    );
    // 计算光照样式
    coin.style.setProperty(
      "--shine-opacity-multiplier",
      4 * Math.sin((coin.angle + Math.PI / 2) % Math.PI) - 3.2
    );
    coin.style.setProperty(
      "--shine-bg-multiplier",
      -40 * (Math.cos((coin.angle + Math.PI / 2) % Math.PI) - 0.5) + "%"
    );
    // Repeat animation loop
    if (coin.moveLoopCount < coin.maxMoveLoopCount) {
      if (coin.moveLoopCount === coin.maxMoveLoopCount - 6)
        button.classList.add("shrink-landing");
      window.requestAnimationFrame(flipCoinLoop);
    } else {
      button.classList.add("coin-landed");
      coin.style.setProperty("opacity", 0);
      setTimeout(() => {
        button.classList.remove("clicked", "shrink-landing", "coin-landed");
        setTimeout(() => {
          resetCoin();
        }, 300);
      }, 1500);
    }
  };
  // 重置按钮
  const resetCoin = () => {
    coin.style.setProperty("--coin-x-multiplier", 0);
    coin.style.setProperty("--coin-scale-multiplier", 0);
    coin.style.setProperty("--coin-rotation-multiplier", 0);
    coin.style.setProperty("--shine-opacity-multiplier", 0.4);
    coin.style.setProperty("--shine-bg-multiplier", "50%");
    coin.style.setProperty("opacity", 1);
    // Delay to give the reset animation some time before you can click again
    setTimeout(() => {
      button.clicked = false;
    }, 300);
  };
});


相关文章
|
7月前
|
Java 程序员 测试技术
我有一个朋友写出了17种触发NPE的代码!避免这些坑
我有一个朋友,写代码的时候常常遭到NPE背刺,痛定思痛,总结了NPE出没的17个场景,哪一个你还没有遇到过?
|
7月前
|
JSON JavaScript 前端开发
抓住异常,解救你的代码世界:你应该了解的 JavaScript 异常类型
抓住异常,解救你的代码世界:你应该了解的 JavaScript 异常类型
|
3月前
|
数据可视化 Java 程序员
自定义异常,让你的代码不再着急
简介:DataV-Atlas提供可视分析地图服务,含3个项目和100M存储空间,助您轻松管理数据。立即试用!DataV还提供5个大屏展示模板,免费试用1个月。通过自定义异常提升Java代码质量,让编程更加优雅高效。
25 1
|
7月前
|
Java 程序员 数据安全/隐私保护
Java中的异常语法知识居然这么好玩!后悔没有早点学习
Java中的异常语法知识居然这么好玩!后悔没有早点学习
70 1
|
安全 Java 程序员
【C++杂货铺】一文总结C++中的异常
【C++杂货铺】一文总结C++中的异常
45 0
|
程序员
有了这些不愁找不到对象,520表白代码
有了这些不愁找不到对象,520表白代码
87 0
|
Java 数据库连接
异常处理一:抓抛模型
异常处理一:抓抛模型
76 0
|
缓存 前端开发 Java
支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!
支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!
159 0
支付宝二面:使用 try-catch 捕获异常会影响性能吗?大部分人都会答错!
|
Java 数据库连接 数据库
啪,还敢抛出异常
啪,还敢抛出异常
203 0
啪,还敢抛出异常
|
Java 程序员 数据库
Java异常处理机制(完结篇)——再看不懂我找不到女朋友
Java异常处理机制(完结篇)——再看不懂我找不到女朋友
154 0
Java异常处理机制(完结篇)——再看不懂我找不到女朋友