js实现洗牌动画
洗牌动画实现思路
洗牌动画的核心是通过JavaScript动态调整DOM元素的顺序和位置,模拟扑克牌洗牌的效果。关键点包括元素位置计算、动画过渡和随机排序。
基本HTML结构
创建一个简单的扑克牌容器,每张牌用div元素表示:
<div class="deck">
<div class="card">A</div>
<div class="card">2</div>
<div class="card">3</div>
<!-- 更多牌... -->
</div>
CSS样式设置
为卡片添加基本样式和过渡效果:
.deck {
position: relative;
width: 300px;
height: 200px;
}
.card {
position: absolute;
width: 50px;
height: 80px;
background: white;
border: 1px solid black;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.5s ease;
}
JavaScript洗牌逻辑
使用Fisher-Yates算法进行随机排序,并添加动画:
function shuffleDeck() {
const deck = document.querySelector('.deck');
const cards = Array.from(deck.children);
// Fisher-Yates洗牌算法
for (let i = cards.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[cards[i], cards[j]] = [cards[j], cards[i]];
}
// 更新DOM顺序
cards.forEach(card => deck.appendChild(card));
// 添加动画效果
cards.forEach((card, index) => {
const x = Math.random() * 200 - 100; // 随机x偏移
const y = Math.random() * 100 - 50; // 随机y偏移
const rot = Math.random() * 30 - 15; // 随机旋转
card.style.transform = `translate(${x}px, ${y}px) rotate(${rot}deg)`;
// 延迟重置位置
setTimeout(() => {
card.style.transform = `translate(${index * 10}px, 0) rotate(0deg)`;
}, 500);
});
}
// 调用洗牌函数
shuffleDeck();
进阶动画效果
添加更真实的洗牌动画,模拟手部洗牌动作:
function advancedShuffle() {
const deck = document.querySelector('.deck');
const cards = Array.from(deck.children);
const animationDuration = 1000;
// 分阶段动画
cards.forEach((card, i) => {
// 第一阶段:散开
card.style.transition = `transform ${animationDuration/2}ms ease`;
card.style.transform = `
translate(${Math.random()*200-100}px, ${Math.random()*100-50}px)
rotate(${Math.random()*60-30}deg)
`;
// 第二阶段:重新收集
setTimeout(() => {
card.style.transition = `transform ${animationDuration/2}ms ease`;
card.style.transform = `translate(${i*10}px, 0) rotate(0deg)`;
// 更新DOM顺序
setTimeout(() => deck.appendChild(card), animationDuration/2);
}, animationDuration/2 + i*50);
});
}
性能优化建议
对于大量元素的动画,考虑使用CSS硬件加速:
.card {
will-change: transform;
transform: translateZ(0);
}
使用requestAnimationFrame替代setTimeout可以获得更流畅的动画效果:

function animateShuffle() {
let start = null;
const duration = 1000;
function step(timestamp) {
if (!start) start = timestamp;
const progress = (timestamp - start) / duration;
// 更新动画状态
// ...
if (progress < 1) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
}






