如何让3D立方体从上次动画结束位置继续执行随机触发的动画?
解决3D立方体从上次动画结束位置继续动画的问题
嘿,这个问题我之前做3D骰子动画时也踩过坑!核心原因是你现在用的@keyframes里,每个动画的0%帧都是固定的初始transform状态,而且每次重新设置animation属性时,浏览器会强制把元素重置回动画的起始位置,所以才会每次点击都跳回原点再执行动画。
下面给你一个简单直接的解决方案,不用依赖@keyframes,而是用JavaScript跟踪当前的旋转状态,配合CSS transition来实现连续的动画:
修改后的代码
CSS部分
.scene { perspective:200px; width:100px; height:100px; } .die { position:relative; width:100%; height:100%; transform-style:preserve-3d; transform: translateZ(-50px); transition: transform 2s ease; /* 把动画过渡效果统一放在这里 */ } .face { position:absolute; width:100px; height:100px; color:white; top:0; bottom:0; left:0; right:0; background-color:purple; } .one { transform: rotateY(0deg) translateZ(50px); } .two { transform:rotateY(90deg) translateZ(50px); } .three { transform:rotateY(180deg) translateZ(50px); } .four { transform:rotateY(-90deg) translateZ(50px); } .five { transform:rotateX(90deg) translateZ(50px); } .six { transform:rotateX(-90deg) translateZ(50px); } /* 移除原来的@keyframes,我们用动态修改transform来实现动画 */
JavaScript部分
// 用变量跟踪当前的X、Y轴旋转角度,初始值和元素初始transform对应 let currentRotX = 0; let currentRotY = 0; // 提前获取骰子元素,避免每次点击都重新查询DOM const dieElement = document.getElementById("die"); function spinDie() { // 修复原代码的随机数问题:Math.random()*1只会生成0,改成*2才能得到1或2 const randomNum = Math.floor(Math.random() * 2) + 1; if (randomNum === 1) { // 对应原动画one:X轴旋转360度,Y轴保持不变 currentRotX += 360; } else if (randomNum === 2) { // 对应原动画two:X轴旋转360度,Y轴额外减90度 currentRotX += 360; currentRotY -= 90; } // 基于当前旋转状态设置新的transform,transition会自动处理过渡动画 dieElement.style.transform = `translateZ(-50px) rotateY(${currentRotY}deg) rotateX(${currentRotX}deg)`; }
HTML部分(无需修改,保持原结构即可)
<div class="scene"> <div class="die" id="die" onclick="spinDie()"> <div class="face one">one </div> <div class="face two">two </div> <div class="face three">three </div> <div class="face four">four </div> <div class="face five">five </div> <div class="face six">six </div> </div> </div>
为什么这个方案有效?
- 我们用变量
currentRotX和currentRotY持续跟踪骰子当前的旋转状态,每次点击都是在现有角度的基础上累加新的旋转量,而不是回到初始状态。 - CSS的
transition属性会自动识别元素当前的transform值和新设置的transform值,平滑过渡这两个状态之间的变化,完美实现“从上次结束位置继续动画”的效果。 - 顺便修复了原代码里随机数的bug:原代码
Math.floor(Math.random() * 1) + 1永远只会得到1,改成Math.random() * 2才能随机生成1或2,触发两种不同的动画效果。
内容的提问来源于stack exchange,提问作者user13398128
相关产品推荐
相关产品推荐

