A Dice With Advanced Animation
<m-model id="dice" src="https://public.mml.io/dice.glb" y="1" collide="true" onclick="rollDice()">
<m-attr-anim id="rx" attr="rx" ping-pong="false" easing="linear" start="0" end="0" loop="false" start-time="0" duration="1"></m-attr-anim>
<m-attr-anim id="ry" attr="ry" ping-pong="false" easing="linear" start="0" end="0" loop="false" start-time="0" duration="1"></m-attr-anim>
<m-attr-anim id="rz" attr="rz" ping-pong="false" easing="linear" start="0" end="0" loop="false" start-time="0" duration="1"></m-attr-anim>
<m-attr-anim id="y" attr="y" ping-pong="false" easing="linear" start="1" end="1" loop="false" start-time="0" duration="1"></m-attr-anim>
</m-model>
<script>
let rolling = false;
let rollResult = 1;
let rollDuration = 750;
let rollHeight = 3.1;
function radToDeg(radians) {
return radians * (180 / Math.PI);
}
function animate(attr, easing, targetRotation, duration) {
rolling = true;
const mAttrAnim = document.getElementById(attr);
const newStart = mAttrAnim.getAttribute("end");
mAttrAnim.setAttribute("easing", easing);
mAttrAnim.setAttribute("start", newStart);
mAttrAnim.setAttribute("end", targetRotation);
mAttrAnim.setAttribute("loop", "false");
mAttrAnim.setAttribute("duration", duration);
mAttrAnim.setAttribute("start-time", document.timeline.currentTime);
setTimeout(() => {
rolling = false;
}, duration + 10);
}
function rollDice() {
if (rolling) return;
const rollMap = {
1: {
rx: 0,
ry: 0,
rz: 0
},
2: {
rx: 0,
ry: 0,
rz: radToDeg(-Math.PI / 2)
},
3: {
rx: radToDeg(-Math.PI / 2),
ry: 0,
rz: 0
},
4: {
rx: radToDeg(Math.PI / 2),
ry: 0,
rz: 0
},
5: {
rx: 0,
ry: 0,
rz: radToDeg(Math.PI / 2)
},
6: {
rx: radToDeg(Math.PI),
ry: 0,
rz: 0
},
};
const diceElement = document.getElementById("dice");
let newRoll = Math.floor(Math.random() * 6) + 1;
while (newRoll === rollResult) {
newRoll = Math.floor(Math.random() * 6) + 1;
}
rollResult = newRoll;
const targetRotation = rollMap[rollResult];
const startRotation = {
rx: parseFloat(diceElement.getAttribute("rx")),
ry: parseFloat(diceElement.getAttribute("ry")),
rz: parseFloat(diceElement.getAttribute("rz")),
};
animate("rx", "easeOutCubic", targetRotation.rx, rollDuration);
animate("ry", "easeOutCubic", targetRotation.ry, rollDuration);
animate("rz", "easeOutCubic", targetRotation.rz, rollDuration);
animate("y", "easeOutQuint", rollHeight, rollDuration * 0.35);
setTimeout(() => {
animate("y", "easeOutBounce", 1, rollDuration * 0.65);
}, rollDuration * 0.35);
}
</script>
Interactive web page -> https://mml.io/examples?example=Dice
Last updated