如何实现CSS关键帧动画平滑衔接:中途点击从当前状态过渡
解决动画中途点击从当前状态触发关闭的问题
核心思路和你设想的一致,通过JS实时记录元素的当前状态,点击时动态修改动画的起始参数,具体实现步骤如下:
- 实时捕获当前状态:每次点击触发动画切换前,用
getBoundingClientRect()获取元素实时的宽高、位置信息,将这些值存入变量保存。 - 动态生成关闭动画关键帧:不用固定的CSS关键帧,而是通过JS创建
@keyframes规则,把关闭动画的from值设为刚才保存的当前状态,to值设为初始的小矩形尺寸。 - 重置动画触发逻辑:切换动画前先移除旧的动画类,通过读取
offsetWidth强制触发浏览器重排,再添加新的动画类,确保动画从新的起始状态运行。
具体代码示例
// 存储元素实时状态的变量 let currentState = {}; // 点击切换动画的处理函数 const toggleAnimation = () => { const box = document.querySelector('.box'); const isExpanded = box.classList.contains('expanded'); // 获取元素当前的实时位置与尺寸 const rect = box.getBoundingClientRect(); currentState = { width: `${rect.width}px`, height: `${rect.height}px`, top: `${rect.top}px`, left: `${rect.left}px` }; if (isExpanded) { // 动态生成关闭动画的关键帧 const closeKeyframes = `@keyframes close { from { width: ${currentState.width}; height: ${currentState.height}; top: ${currentState.top}; left: ${currentState.left}; transform: none; } to { width: 100px; height: 100px; top: 50%; left: 50%; transform: translate(-50%, -50%); } }`; // 插入关键帧到页面样式表 const styleEl = document.createElement('style'); styleEl.textContent = closeKeyframes; document.head.appendChild(styleEl); // 重置动画状态,确保从当前状态开始播放 box.classList.remove('expanded'); void box.offsetWidth; // 强制触发重排,清除旧动画状态 box.classList.add('closing'); } else { // 展开动画逻辑,移除关闭类后触发展开动画 box.classList.remove('closing'); void box.offsetWidth; box.classList.add('expanded'); } }; // 绑定点击事件 document.querySelector('.box').addEventListener('click', toggleAnimation);
对应的基础CSS样式:
.box { position: fixed; width: 100px; height: 100px; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #2c3e50; cursor: pointer; } .expanded { animation: expand 0.6s forwards; } @keyframes expand { to { width: 100vw; height: 100vh; top: 0; left: 0; transform: none; } } .closing { animation: close 0.6s forwards; }
注意事项
- 每次生成新关键帧时,可给关键帧名称加时间戳等唯一标识,避免样式冲突;或者在插入新样式前移除旧的样式元素,防止样式表冗余。
- 若需要支持更复杂的动画属性(比如背景色、圆角),只需在
currentState中添加对应属性的实时值,同步到关键帧即可。
内容的提问来源于stack exchange,提问作者HelloToxicity
相关产品推荐
相关产品推荐

