前端三件套实现一个摇骰子功能

说在前面

微信的摇骰子表情包大家应该都玩过吧,今天我们也来尝试来简单实现一个摇骰子的功能。

效果展示

点数绘制

首先我们需要将六个面的点数先绘制出来,这里我直接用flex布局一把梭

1点
<div class="face front" data-value="1">
  <div class="dot" style="background-color: red"></div>
</div>

2点
<div class="face bottom" data-value="2">
  <div class="row">
    <div class="dot"></div>
    <div class="dot hide-dot"></div>
    <div class="dot"></div>
  </div>
</div>

3点
<div class="face right" data-value="3">
  <div class="row">
    <div class="dot hide-dot"></div>
    <div class="dot hide-dot"></div>
    <div class="dot"></div>
  </div>
  <div class="row">
    <div class="dot hide-dot"></div>
    <div class="dot"></div>
    <div class="dot hide-dot"></div>
  </div>
  <div class="row">
    <div class="dot"></div>
    <div class="dot hide-dot"></div>
    <div class="dot hide-dot"></div>
  </div>
</div>

4点
<div class="face left" data-value="4">
  <div class="row">
    <div class="dot hide-dot"></div>
  </div>
  <div class="row">
    <div class="dot" style="background-color: red"></div>
    <div class="dot hide-dot"></div>
    <div class="dot" style="background-color: red"></div>
  </div>
  <div class="row">
    <div class="dot hide-dot"></div>
  </div>
  <div class="row">
    <div class="dot" style="background-color: red"></div>
    <div class="dot hide-dot"></div>
    <div class="dot" style="background-color: red"></div>
  </div>
  <div class="row">
    <div class="dot hide-dot"></div>
  </div>
</div>

5点
<div class="face top" data-value="5">
  <div class="row">
    <div class="dot"></div>
    <div class="dot hide-dot"></div>
    <div class="dot"></div>
  </div>
  <div class="row">
    <div class="dot"></div>
  </div>
  <div class="row">
    <div class="dot"></div>
    <div class="dot hide-dot"></div>
    <div class="dot"></div>
  </div>
</div>

6点
<div class="face back" data-value="6">
  <div class="row" style="margin-right: 15px">
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
  </div>
  <div class="row">
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
  </div>
</div>

涉及css样式代码
/* 骰子面通用样式 */
.face {
  position: absolute;
  width: 180px;
  height: 180px;
  background: #fff;
  border: 2px solid #333;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.row {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

/* 点数布局 */
.dot {
  width: 30px;
  height: 30px;
  background: #333;
  border-radius: 50%;
  margin: 10px;
}
/* 占位点数 */
.hide-dot {
  visibility: hidden;
}

正方体拼接

直接使用css的transform对每一面的空间位置做下调整即可。

/* 各面3D变换 */
.front {
  transform: translateZ(90px);
}
.back {
  transform: rotateY(180deg) translateZ(90px);
}
.top {
  transform: rotateX(90deg) translateZ(90px);
}
.bottom {
  transform: rotateX(-90deg) translateZ(90px);
}
.left {
  transform: rotateY(-90deg) translateZ(90px);
}
.right {
  transform: rotateY(90deg) translateZ(90px);
}

配置旋转映射表

const rotateMap = {
  1: {
    rotateX: "0deg",
    rotateY: "0deg",
  },
  2: {
    rotateX: "90deg",
    rotateY: "0deg",
  },
  3: {
    rotateX: "180deg",
    rotateY: "90deg",
  },
  4: {
    rotateX: "0deg",
    rotateY: "90deg",
  },
  5: {
    rotateX: "270deg",
    rotateY: "0deg",
  },
  6: {
    rotateX: "0deg",
    rotateY: "180deg",
  },
};

定义了每个点数对应的三维旋转角度。

旋转骰子

1、获取骰子点数

首先需要一个获取随机数的方法用于获取骰子点数。

function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
2、旋转骰子
function rollDice() {
  const dice = document.getElementById("dice");
  const result = document.getElementById("result");
  const rollBtn = document.getElementById("rollBtn");
  const randomValue = getRandom(1, 6);
  const obj = rotateMap[randomValue];
  let transform = "",
    transform2 = "";
  for (const key in obj) {
    transform += `${key}(${obj[key]}) `;
    transform2 += `${key}(${parseInt(obj[key]) + 360 * 2}deg) `;
  }
  dice.style.transition = "transform 2s cubic-bezier(0.25, 0.1, 0.25, 1)";
  dice.style.transform = transform2;
  rollBtn.disabled = true;
  rollBtn.style.background = "#ccc";
  result.textContent = `正在摇骰子...`;

  setTimeout(() => {
    dice.style.transition = "none";
    dice.style.transform = transform;
    rollBtn.disabled = false;
    rollBtn.style.background = "#2196f3";
    result.textContent = `点数:${randomValue}`;
  }, 2100);
}
  • 双重动画欺骗:采用两阶段CSS变换——先用transform2执行720度加速旋转(通过parseInt(obj[key]) + 360 * 2实现),随后瞬间切换为实际点数的transform,这种视觉差手法既保证了2秒的观赏性动画,又能准确定位最终点数。
  • 交互状态管理:通过setTimeout和按钮的disabled属性实现完整的交互闭环:点击后立即禁用按钮、切换背景色,待2.1秒动画结束后恢复交互,同时更新DOM元素显示最终点数。过渡曲线cubic-bezier(0.25, 0.1, 0.25, 1)的设定使旋转呈现先快后慢的物理惯性效果。

源码

demo源码已上传到gitee,有兴趣的也可以到这里看看:https://gitee.com/zheng_yongtao/video-code


  • 🌟觉得有帮助的可以点个star~

  • 🖊有什么问题或错误可以指出,欢迎pr~

  • 📬有什么想要实现的功能或想法可以联系我~


公众号

关注公众号『 前端也能这么有趣 』,获取更多有趣内容。

发送 加群 还可以加入群聊,一起来学习(摸鱼)吧~

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JYeontu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值