如何停止当前SVG循环动画函数并切换触发另一组动画函数?
实现SVG动画切换:停止当前动画并切换到另一组
要实现点击切换SVG动画的需求,核心是跟踪当前动画状态并正确终止正在运行的动画,然后启动另一组动画。下面分两种常见的动画实现场景给出具体方案:
场景1:用requestAnimationFrame实现的JS动画
如果你的动画是通过JS的requestAnimationFrame递归调用实现的,可以按以下步骤处理:
- 维护全局状态变量:用来保存当前动画的ID(用于终止)和当前运行的动画类型。
- 封装动画启动函数:每个动画组对应一个启动函数(也就是你说的"Up函数"),启动前先终止之前的动画。
- 点击切换逻辑:判断当前动画类型,终止后启动另一组动画。
示例代码:
// 全局状态:跟踪当前动画ID和类型 let currentAnimId = null; let currentAnimType = 'horizontal'; // 水平动画核心逻辑 function runHorizontalAnim() { // 这里写你的SVG水平动画逻辑,比如修改元素的x坐标/transform const svgElem = document.getElementById('mySvg'); let currentX = parseFloat(svgElem.getAttribute('x')) || 0; currentX += 1; if (currentX > 300) currentX = 0; svgElem.setAttribute('x', currentX); // 更新动画ID,方便后续终止 currentAnimId = requestAnimationFrame(runHorizontalAnim); } // 水平动画的启动函数(你的"Up函数") function startHorizontalAnim() { // 先终止之前的动画 if (currentAnimId) cancelAnimationFrame(currentAnimId); currentAnimType = 'horizontal'; runHorizontalAnim(); } // 垂直动画核心逻辑 function runVerticalAnim() { // SVG垂直动画逻辑,比如修改y坐标/transform const svgElem = document.getElementById('mySvg'); let currentY = parseFloat(svgElem.getAttribute('y')) || 0; currentY += 1; if (currentY > 200) currentY = 0; svgElem.setAttribute('y', currentY); currentAnimId = requestAnimationFrame(runVerticalAnim); } // 垂直动画的启动函数(你的另一组"Up函数") function startVerticalAnim() { if (currentAnimId) cancelAnimationFrame(currentAnimId); currentAnimType = 'vertical'; runVerticalAnim(); } // 点击切换函数 function toggleSvgAnim() { // 先终止当前动画 if (currentAnimId) cancelAnimationFrame(currentAnimId); // 切换到另一组动画 if (currentAnimType === 'horizontal') { startVerticalAnim(); } else { startHorizontalAnim(); } } // 绑定点击事件,比如给按钮加点击触发 document.getElementById('toggleBtn').addEventListener('click', toggleSvgAnim);
场景2:用CSS类控制的动画
如果你的动画是通过CSS @keyframes + 类名实现的,切换逻辑会更简单:
- 定义两组动画类:分别对应水平和垂直动画。
- 点击切换时移除当前类,添加目标类:浏览器会自动终止旧动画并启动新动画。
示例代码:
CSS部分:
/* 水平动画类 */ .svg-horizontal-anim { animation: horizontalSlide 3s linear infinite; } /* 垂直动画类 */ .svg-vertical-anim { animation: verticalSlide 3s linear infinite; } @keyframes horizontalSlide { 0% { transform: translateX(0); } 100% { transform: translateX(250px); } } @keyframes verticalSlide { 0% { transform: translateY(0); } 100% { transform: translateY(180px); } }
JS部分:
const svgElem = document.getElementById('mySvg'); let currentAnimType = 'horizontal'; // 初始化启动第一组动画 svgElem.classList.add('svg-horizontal-anim'); function toggleSvgAnim() { // 移除当前动画类,停止旧动画 svgElem.classList.remove(`svg-${currentAnimType}-anim`); // 切换动画类型 currentAnimType = currentAnimType === 'horizontal' ? 'vertical' : 'horizontal'; // 添加新动画类,启动新动画 svgElem.classList.add(`svg-${currentAnimType}-anim`); } // 绑定点击事件 document.getElementById('toggleBtn').addEventListener('click', toggleSvgAnim);
额外注意点
- 如果切换时需要动画无缝衔接,记得在终止旧动画后重置SVG元素的位置/状态,避免突兀跳转。
- 对于
requestAnimationFrame的动画,一定要确保每次递归调用都更新currentAnimId,否则无法正确终止。
内容的提问来源于stack exchange,提问作者cal
相关产品推荐
相关产品推荐

