如何用JavaScript动态设置CSS动画关键帧实现加购动效?
实现商品加入购物车的动画效果需求
我想在商品页面实现一个动画效果:当用户点击“加入购物车”时,商品图片会动画式地移动并缩小至导航栏的购物车图标处。现有示例代码如下:
HTML代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="test"></div>
CSS代码
.test { position : fixed; top : 200px; left : 600px; background : red; width : 200px; height : 300px; } @keyframes toCart { 25% { top : 850px; left : 550px; width : 200px; height : 300px; } 100% { top : 100px; left : 1100px; width : 0; height : 0 } } .animateTest { animation : toCart 2s; }
JavaScript代码
$('div.test').on('animationend', (e) => { $(e.target).remove(); }) // 用户点击触发 $('div.test').addClass('animateTest');
目前的难点是用户视口存在差异,我已经能用JS获取购物车图标的位置:
whereIsCart = $('#cartIcon').offset()
希望能把@keyframes的100%关键帧动态设置为购物车的位置:
100% { top : whereIsCart.top; left : whereIsCart.left; width : 0; height : 0 }
请问该如何实现?或者有没有更优的方案达成这一目标?
解决方案
下面提供几种实用的实现方案,适配不同场景需求:
方案一:动态创建CSS关键帧
通过JS动态生成包含购物车实时位置的@keyframes规则,完美适配不同视口的位置差异:
// 绑定加入购物车按钮点击事件 $('.add-to-cart').click(function() { // 获取购物图标的实时位置 const cartOffset = $('#cartIcon').offset(); // 克隆当前商品的图片(避免影响原元素) const $productImg = $(this).closest('.product').find('img').clone(); // 设置克隆元素的初始定位(和原图片位置一致) const productOffset = $productImg.offset(); $productImg.css({ position: 'fixed', top: productOffset.top + 'px', left: productOffset.left + 'px', width: $productImg.width() + 'px', height: $productImg.height() + 'px', zIndex: 9999, pointerEvents: 'none' // 防止动画元素遮挡页面交互 }).appendTo('body'); // 动态生成关键帧样式 const keyframes = ` @keyframes toCart { 100% { top: ${cartOffset.top}px; left: ${cartOffset.left}px; width: 0; height: 0; opacity: 0; } } `; // 创建style标签并插入到页面头部 const style = document.createElement('style'); style.innerHTML = keyframes; document.head.appendChild(style); // 给克隆元素添加动画类触发动画 $productImg.addClass('animate-to-cart'); // 动画结束后清理元素和动态样式 $productImg.on('animationend', function() { $(this).remove(); style.remove(); }); });
配套的基础CSS:
.animate-to-cart { animation: toCart 1.5s ease-in-out forwards; }
方案二:CSS变量+JS赋值(更高效)
利用CSS变量存储动态位置,无需每次创建新的关键帧,性能更优:
先写基础CSS
@keyframes toCart { 100% { top: var(--cart-top); left: var(--cart-left); width: 0; height: 0; opacity: 0; } } .animate-to-cart { animation: toCart 1.5s ease-in-out forwards; position: fixed; z-index: 9999; pointer-events: none; }
再写JS逻辑
$('.add-to-cart').click(function() { const cartOffset = $('#cartIcon').offset(); const $productImg = $(this).closest('.product').find('img').clone(); const productOffset = $productImg.offset(); // 设置初始位置并给元素赋值CSS变量 $productImg.css({ top: productOffset.top + 'px', left: productOffset.left + 'px', width: $productImg.width() + 'px', height: $productImg.height() + 'px', '--cart-top': cartOffset.top + 'px', '--cart-left': cartOffset.left + 'px' }).appendTo('body').addClass('animate-to-cart'); // 动画结束后移除元素 $productImg.on('animationend', function() { $(this).remove(); }); });
方案三:Web Animations API(纯JS控制,更灵活)
直接用JS的Web Animations API控制动画,不需要依赖CSS关键帧,适合需要复杂动态逻辑的场景:
$('.add-to-cart').click(function() { const cartOffset = $('#cartIcon').offset(); const $productImg = $(this).closest('.product').find('img').clone(); const productOffset = $productImg.offset(); const imgWidth = $productImg.width(); const imgHeight = $productImg.height(); // 设置克隆元素的初始样式 $productImg.css({ position: 'fixed', top: productOffset.top + 'px', left: productOffset.left + 'px', width: imgWidth + 'px', height: imgHeight + 'px', zIndex: 9999, pointerEvents: 'none' }).appendTo('body'); // 使用Web Animations API执行动画 $productImg[0].animate([ // 初始状态 { transform: 'translate(0, 0)', opacity: 1, width: imgWidth + 'px', height: imgHeight + 'px' }, // 结束状态:移动到购物车位置并缩小消失 { transform: `translate(${cartOffset.left - productOffset.left}px, ${cartOffset.top - productOffset.top}px)`, opacity: 0, width: '0px', height: '0px' } ], { duration: 1500, // 动画时长1.5秒 easing: 'ease-in-out' // 缓动效果 }).onfinish = function() { // 动画结束后移除元素 $productImg.remove(); }; });
内容的提问来源于stack exchange,提问作者shenkwen
相关产品推荐
相关产品推荐

