cytoscape.js 核心动画停止 API:cy.stop() 用法、参数与底层实现解析
2026/9/24 1:06:37 网站建设 项目流程
  • 数据可视化

【免费下载链接】cytoscape.js

Graph theory (network) library for visualisation and analysis

项目地址:https://gitcode.com/gh_mirrors/cy/cytoscape.js
点击查看免费下载

本文围绕 cytoscape.js 核心 API 中的cy.stop()方法展开,讲解如何中断视口级动画(如fitpanzoom等核心动画),并结合仓库源码剖析其clearQueuejumpToEnd两个可选参数的真实作用,以及它与ele.stop()ani.stop()的关系。读完本文,你将能在实际项目中精准地控制动画的暂停、中止与清理,避免动画队列堆积造成的性能问题。

一、为什么需要cy.stop()

cytoscape.js 中,cy.animate()用于对核心视口(viewport)发起平滑动画,例如平移(pan)、缩放(zoom)、适配元素(fit)等。这类动画默认会完整播放到结束为止,但在交互式应用中,用户往往会在动画中途触发新的操作(比如拖拽、滚轮缩放、切换视图)。此时如果旧动画继续播放,会与新操作互相"打架",导致视口位置错乱或卡顿。

cy.stop()就是为此设计的:它立即终止当前正在播放的核心动画,让视口停留在当前状态,并把控制权交还给开发者。

二、基本用法:完整示例

documentation/md/core/stop.md给出了最典型的应用场景——在动画播放中途将其停止:

cy.animate({ fit: { eles: '#j' } }, { duration: 2000 }); // stop in the middle setTimeout(function(){ cy.stop(); }, 1000);

这段代码的含义是:

  1. 先让视口用 2000ms 平滑地缩放、平移以适配元素#jfit动画);
  2. 在动画进行到一半(1000ms)时调用cy.stop()
  3. 动画被立即中断,视口停留在 1000ms 时刻对应的中间位置。

这里的fit属于核心级动画,只有cy.stop()(而不是元素集合的stop())能够中止它。关于cy.animate()的更多可用属性(panzoomfitduration等),可参考 documentation/md/core/animate.md。

三、cy.stop()的两个可选参数:clearQueuejumpToEnd

从 src/define/animation.mjs 的源码可以看到,stop的实现签名是:

stop: function(){ return function stopImpl( clearQueue, jumpToEnd ){ // ... }; }

cy.stop( clearQueue, jumpToEnd ),两个参数都是可选的布尔值,默认为false

参数类型默认值作用
clearQueuebooleanfalse是否清空尚未执行的动画队列(queue)。为true时,排队等待播放的后续动画全部被丢弃;为false时,队列中的动画在停止后仍会继续依次播放。
jumpToEndbooleanfalse是否直接跳到动画终点。为true时,当前动画立即完成(跳到最终状态);为false时,动画停留在当前进度。

从源码看两个参数的真实行为

在 src/define/animation.mjs 中,实现逻辑非常直白:

for( let j = 0; j < anis.length; j++ ){ let ani = anis[ j ]; let ani_p = ani._private; if( jumpToEnd ){ // next iteration of the animation loop, the animation // will go straight to the end and be removed ani_p.duration = 0; } } // clear the queue of future animations if( clearQueue ){ _p.animation.queue = []; } if( !jumpToEnd ){ _p.animation.current = []; }

关键点如下:

  • jumpToEnd: true的实现技巧:它并不直接改写进度,而是把当前动画的duration置为0。在动画循环中,duration === 0时进度会被直接判定为1(见 src/core/animation/step.mjs),于是下一次循环迭代时动画"直接走到终点"并自然完成,随后触发complete回调。这保证了跳转终点时动画的收尾逻辑(回调、样式最终态)仍然完整执行。
  • clearQueue: true:直接清空目标对象私有状态_p.animation.queue中的全部排队动画,实现"停止并清空后续任务"的效果。
  • 立即停止(两者皆默认 false):将_p.animation.current置为空数组,正在播放的动画即刻从当前帧中断,既不走完也不跳终。

无论采用哪种组合,方法末尾都会调用cy.notify('draw')触发一次重绘通知——源码注释特别说明:"the animation loop doesn't do it for us onstop",即停止动作本身不会经由动画循环触发渲染通知,因此需要显式通知渲染器刷新画面(见 src/define/animation.mjs)。

典型组合场景

// 立即停止当前动画,同时丢弃后续排队的动画 cy.stop( true ); // 立即跳到动画终点(常用于"快速完成过渡") cy.stop( false, true ); // 停止当前动画并清空队列,然后直接跳到终点 cy.stop( true, true );

四、底层原理:cy.stop()在动画系统中的位置

要理解cy.stop(),需要先了解 cytoscape.js 的动画运行模型:

  1. 动画对象cy.animation()/cy.animate()会创建一个Animation实例(见 src/animation.mjs),内部记录durationprogressplayingstarted等状态,以及目标对象的起始与终止位置、平移、缩放、样式。
  2. 挂载队列Animation.prototype.hook()将动画挂到目标对象的_private.animation.queue(排队)或current(当前播放)列表;元素动画还会通过cy.addToAnimationPool()把元素加入动画池(见 src/core/animation/index.mjs 与 src/animation.mjs)。
  3. 动画循环:核心的stepAll()每帧遍历动画池中的元素与核心实例,先从queue取出下一个动画放入current,再逐帧调用step()计算插值并应用(见 src/core/animation/step-all.mjs 与 src/core/animation/step.mjs)。动画结束后从current移除并触发complete回调。

cy.stop()正是作用于上述模型中的第 2、3 步:它直接操作核心实例_private.animationcurrentqueue两个列表,绕开动画循环,立即改变状态。同时,stop方法被挂在核心对象的原型方法集中(stop: define.stop(),见 src/core/animation/index.mjs),因此cy、元素(ele)和元素集合共用同一份stopImpl实现——区别仅在于this指向的目标不同。

ele.stop()ani.stop()的区别

cytoscape.js 中有三个容易混淆的stop,它们服务不同粒度:

方法目标用途参考
cy.stop()核心实例停止视口动画(pan / zoom / fit / center 等)documentation/md/core/stop.md
ele.stop()/collection.stop()元素 / 元素集合停止元素的位置、样式动画documentation/md/collection/stop.md
ani.stop()单个 Animation 对象停止指定的单个动画实例,便于清理和复用documentation/md/animation/stop.md

Animation.prototype.stop的实现中(见 src/animation.mjs),动画实例被标记为stopped = true并从播放状态摘除;随后动画循环在 src/core/animation/step-all.mjs 中检测到ani_p.stopped时将其从current列表移除并复位hookedplayingstarted状态。

例如,元素动画的停止示例(来自 documentation/md/collection/stop.md):

cy.nodes().animate({ style: { 'background-color': 'cyan' } }, { duration: 5000, complete: function(){ console.log('Animation complete'); } }); console.log('Animating nodes...'); setTimeout(function(){ console.log('Stopping nodes animation'); cy.nodes().stop(); }, 2500);

五、实践建议与注意事项

  1. 动画对象需要显式清理documentation/md/animation/stop.md明确指出,未被停止的动画对象无法被垃圾回收,除非其关联目标(元素或核心实例)一并被回收。在存在大量动画的场景中,应当对不再需要的动画调用ani.stop()或对应的ele.stop()/cy.stop(),以减少动画循环每帧检查的动画数量,提升帧率。
  2. 停止后仍可复用动画:被stop()的动画对象可以通过play()重新播放(播放时进度若为 1 会自动回卷到 0,见 src/animation.mjs),因此"停止"不等于"销毁"。
  3. 配合交互事件使用:建议在panzoomdrag等用户交互开始前调用cy.stop(),或在切换目标视图时用cy.stop(true)一并清空队列,避免旧动画干扰新操作。
  4. headless(无头)环境注意:在启用样式但无渲染器的 headless 环境中,动画循环由核心自行调度(见 src/core/animation/index.mjs),此时显式调用cy.stop()主动终止动画同样有效,也是避免动画循环空转的手段之一。
  5. 区分布局停止:若需要中止的是布局(layout)而非动画,应使用layout.stop(),布局会在停止时触发layoutstop事件(见 documentation/md/layout/run.md 与 documentation/md/layout/stop.md)。两者机制不同,不可混用。

六、小结

cy.stop()是 cytoscape.js 视口动画控制中"急刹车"能力:通过clearQueue控制是否丢弃排队动画,通过jumpToEnd控制是中途冻结还是直达终点。其实现直取目标对象_private.animationcurrent/queue两个队列并显式触发重绘通知,与ele.stop()ani.stop()共享同一套stopImpl逻辑,构成了覆盖核心、元素、单个动画三个粒度的完整停止 API 体系。理解这些差异与参数语义,能帮助你在复杂的交互场景中精确掌控动画生命周期。

  • 数据可视化

【免费下载链接】cytoscape.js

Graph theory (network) library for visualisation and analysis

项目地址:https://gitcode.com/gh_mirrors/cy/cytoscape.js
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询