说在前面
微信的摇骰子表情包大家应该都玩过吧,今天我们也来尝试来简单实现一个摇骰子的功能。
效果展示
点数绘制
首先我们需要将六个面的点数先绘制出来,这里我直接用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,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。