如何实现带双图的旋转卡片(Flip Card)及模态框联动动画
实现带360°旋转切换的正反卡片及模态框效果
结合CSS 3D变换+关键帧动画,搭配Fancybox实现模态框,以下是完整可行方案:
一、调整HTML结构
为更好控制3D旋转逻辑,给正反卡片增加容器,并改用Fancybox的属性绑定模态框:
<div class="card-container"> <div class="card"> <div class="card-face card-face-front"> <img src="front.jpg" alt="Front of card" data-fancybox="cards" data-src="front.jpg"> </div> <div class="card-face card-face-back"> <img src="back.jpg" alt="Back of card"> </div> </div> </div>
二、CSS实现3D旋转与动画
设置3D空间环境,定义旋转动画序列,初始隐藏卡片背面:
/* 3D透视容器 */ .card-container { perspective: 1000px; width: 300px; height: 420px; cursor: pointer; } .card { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; } /* 卡片正反两面基础样式 */ .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; overflow: hidden; } .card-face-back { transform: rotateY(180deg); /* 初始翻转180度,隐藏背面 */ } .card-face img { width: 100%; height: 100%; object-fit: cover; } /* 正向旋转动画:两次完整360°旋转,过程切换正反 */ @keyframes rotateCycle { 0% { transform: rotateY(0); } 25% { transform: rotateY(180deg); } 50% { transform: rotateY(360deg); } 75% { transform: rotateY(540deg); } 100% { transform: rotateY(720deg); } } /* 反向旋转动画:还原初始状态 */ @keyframes reverseRotateCycle { 0% { transform: rotateY(720deg); } 25% { transform: rotateY(540deg); } 50% { transform: rotateY(360deg); } 75% { transform: rotateY(180deg); } 100% { transform: rotateY(0); } } /* 动画激活类 */ .card.rotate { animation: rotateCycle 1.5s ease-in-out forwards; } .card.reverse-rotate { animation: reverseRotateCycle 1.5s ease-in-out forwards; }
三、JavaScript逻辑(结合Fancybox)
监听卡片点击触发旋转动画,动画结束后打开模态框;监听模态框关闭事件,执行反向旋转:
// 初始化Fancybox Fancybox.bind('[data-fancybox="cards"]', { onClose: (instance) => { const card = instance.trigger.closest('.card'); card.classList.add('reverse-rotate'); // 动画结束后清除类,重置状态 card.addEventListener('animationend', () => { card.classList.remove('reverse-rotate'); }, { once: true }); } }); // 卡片点击事件处理 document.querySelectorAll('.card-container').forEach(container => { container.addEventListener('click', (e) => { e.preventDefault(); const card = container.querySelector('.card'); // 避免动画重复触发 if (card.classList.contains('rotate') || card.classList.contains('reverse-rotate')) return; card.classList.add('rotate'); // 旋转动画结束后打开模态框 card.addEventListener('animationend', () => { card.classList.remove('rotate'); Fancybox.show([{ src: card.querySelector('.card-face-front img').dataset.src }]); }, { once: true }); }); });
关键细节说明
perspective属性提供3D透视效果,让旋转动画更具真实感;backface-visibility: hidden确保旋转时正反卡片不会互相穿透;- 动画关键帧设置两次完整360°旋转,过程中自动切换正反展示,匹配需求;
- 使用
animationend事件监听动画完成,保证旋转与模态框打开的时序正确; - 反向动画在模态框关闭时触发,完整还原初始状态。
内容的提问来源于stack exchange,提问作者ChristosDg
相关产品推荐
相关产品推荐

