Cesium fromGltfAsync加载模型动画不播放的排查指南

最近在做一个基于 Cesium 的仿真展示项目,需要把一批带骨骼动画的机械设备模型加载到三维场景里。模型在 Blender 和本地预览工具里播放都很正常,结果一用fromGltfAsync加载到 Cesium 里,模型能显示,但动画怎么都不动。查了大半天,试了各种姿势,终于把原因摸清了。这篇就记录一下整个排查过程和背后涉及的几个关键点,希望给同样被这个问题卡住的朋友一些参考。

先说结论:fromGltfAsync加载带动画的模型时动画不播放,90% 以上不是模型本身的问题,而是加载方法、时钟绑定和时间轴的配合出了问题。尤其是readyEvent回调里model.clock尚未就绪、animationTimeMode选错、以及忘记调用model.activeAnimations.add这三类问题,占了绝大多数。

1. 先说清楚问题现象与基本机制

1.1 fromGltfAsync 到底是什么

Cesium 从 1.80 版本开始,把原来同步式的Model.fromGltf替换成了异步的Cesium.Model.fromGltfAsync。这个变化表面上是把加载过程从同步变成了返回 Promise,但底层还涉及模型内部资源(纹理、二进制缓冲、着色器)的异步编译。也就是说,你拿到 Model 实例的那一刻,模型并不一定完全就绪。

很多人第一次用fromGltfAsync时,习惯性地按照旧版fromGltf的写法去写:

const model = await Cesium.Model.fromGltfAsync({ url: '/models/robot.glb', modelMatrix: matrix }); viewer.scene.primitives.add(model);

这段代码在加载静态模型时完全没问题,但一旦模型里带动画,就会出现"模型显示了、动画死了"的诡异现象。这里的关键在于,即使拿到了 Model 实例,内部的关联资源(比如时间轴绑定、动画集合初始化)依然可能处于未完成状态。

如果你在await之后立即去操作动画,相当于在模型"睁开眼睛"之前就去让它"跑步",自然跑不起来。

1.2 动画播放背后依赖什么条件

Cesium 的模型动画机制,不是模型自己在那儿放,而是依赖Viewer的clock作为全局时间源。具体流程是这样的:

  1. 模型加载后,会把 glTF 里的 animation 通道解析成ModelAnimationCollection。
  2. 你需要从model.activeAnimations这个集合里手动添加一个动画实例。
  3. 动画的播放进度由model.clock驱动,而这个model.clock默认引用的是viewer.clock。
  4. 只有viewer.clockViewModel和viewer.timeline正常运作,时钟才会持续走。

换句话说,Cesium 模型动画不是"模型自带播放器",而是"模型作为演员,时钟作为导演"。导演不喊开始,演员永远不会动。这也是为什么很多新人搞不懂"明明模型动画没问题,怎么进 Cesium 就不播了"的根本原因。

2. 动画不播放的五种常见诱因

2.1 忘了把时钟接入时间轴

这个坑最常见,也最容易被忽略。我用最小复现案例测试时,用纯Scene初始化,没有创建Viewer,然后再用Model.fromGltfAsync加载。

代码如下:

const scene = new Cesium.Scene({ canvas: canvas, contextOptions: { webgl: { alpha: true } } }); const model = await Cesium.Model.fromGltfAsync({ url: '/models/fan.glb' }); scene.primitives.add(model); model.activeAnimations.addAll();

结果就是不播放。当时我还以为是addAll方法的问题,后来换了几个模型都一样。原因是:纯Scene模式下,没有Clock实例在驱动时间前进。

没有时钟驱动,model.clock.shouldAnimate永远是false,动画系统的 tick 根本不会触发。就算你手动调model.clock.currentTime,也只会动一帧,之后又停住。

解决办法很简单:要么使用Viewer而不是裸Scene,要么手动创建一个Clock并让model.clock引用它:

const clock = new Cesium.Clock({ shouldAnimate: true }); model.clock = clock;

2.2 readyEvent 回调时机的隐蔽陷阱

这是我认为最容易踩、最隐蔽的一个坑。fromGltfAsync返回的 Promise 在模型对象创建后立刻 resolve,但此时model.readyPromise可能还未 fullfill。我之前在这个环节栽了一个多小时,还很困惑为什么 Model 对象拿得到,但访问内部资源时各种诡异。

实际表现是:在fromGltfAsync的await之后直接调用model.activeAnimations.addAll(),动画没有报错,也没效果。因为activeAnimations此时是空集合,你加的动画根本没被解析出来。

正确做法是等待模型进入 ready 状态:

const model = await Cesium.Model.fromGltfAsync({...}); model.readyEvent.addEventListener(() => { // 此时才能安全操作动画 model.activeAnimations.addAll(); });

或者用readyPromise:

await model.readyPromise; model.activeAnimations.addAll();

注意,readyEvent和readyPromise还是有区别的。readyEvent是事件,可能在当前 tick 或下一 tick 触发,而readyPromise是可 await 的 Promise。我习惯优先用readyEvent,因为它在资源就绪后的第一时间触发,不容易遗漏时序。

2.3 animationTimeMode 参数理解偏差

ModelAnimation有个参数叫animationTimeMode,它有三个枚举值:

  • Cesium.ModelAnimationTimeMode.RELATIVE(默认值)
  • Cesium.ModelAnimationTimeMode.ABSOLUTE
  • Cesium.ModelAnimationTimeMode.LOOP_STOP

很多人不知道这个参数存在,结果遇到动画"走了一圈就停了"或者"走到一半突然跳回起点"的情况,还以为是模型的问题。

RELATIVE模式的含义是:动画从 0 秒开始计时,multiplier和delay都是基于动画自己的时间轴。打个比方,就像放DVD时按播放键,从开头开始放,倍速由你控制。

而ABSOLUTE模式喜欢用time属性直接指定动画播放的绝对秒数。如果你把animationTimeMode设成了ABSOLUTE,又没有把time设置为动画时间范围内的值(比如你设了 100 秒,但动画总长只有 5 秒),动画就会卡在最后一帧或完全不显示。

我曾经犯过一个很低级的错误:用ABSOLUTE模式,然后time写了 0.5,动画就卡在中间,看起来像"不会播放"。实际是播放了,只不过被时间卡住了。

另外还有一个高频操作失误:误调用model.animationTime这个属性。其实这个属性是Model类里相对时间偏移,不是动画实例的时间控制。手动改这个值不会让动画正常播放,反而会干扰内部时间轴。

建议:普通场景用默认的RELATIVE就够了,只有在需要精确控制"从第几秒开始播"时才考虑ABSOLUTE,而且一定要设置合理的time值。

2.4 导出的 glTF 本身有问题

这个坑和 Cesium 没有直接关系,但排查时必须重视。

很多从 Blender 导出的 glTF 动画,默认的动画通道可能不是应用到正确的骨骼节点上。我遇到一个客户给的模型,动画在 Sketchfab 上能播,但在 Cesium 里一动不动。后来我用 Babylon.js 的沙盒跑了一下,也是动不了的,这才确定是模型导出环节出了问题。

最典型的例子是 Blender 里用 Armature 绑定的模型,导出 glTF 时如果忘了点选"Use Animation"(旧版叫"Animation"),或者 NLA 编辑器里动画的 action 没有正确关联,导出的 glTF 里根本没有 animation 字段。

判断模型到底有没有正确的动画数据,用文本编辑器打开 glTF 文件,搜"animations":这个关键字。如果没有,那基本可以放弃从 Cesium 侧解决问题了。

另外 glTF 2.0 的标准动画只支持骨骼动画、节点属性动画(位移、旋转、缩放)和 morph target 动画。如果你的模型是贴图 UV 动画或者材质参数动画,这类信息不在动画通道里,Cesium 也不认。

如果确认模型有动画但还是不动,还可以用Cesium.ModelAnimationCollection的length属性来验证:

console.log(model.activeAnimations.length);

始终为 0 就说明动画集合没有正确解析,问题大概率在模型端或加载时序上。

2.5 动画被误暂停或从未启动

activeAnimations.addAll()会把所有动画都加进去并播放。但有一个细节:addAll默认参数是play,它的用法比较直接:

model.activeAnimations.addAll({ speedup: 2 });

这个speedup是播放倍速。如果你手滑写了个 0,动画就会一直在第 0 帧,看起来就像"没有播放"。我当时排查的时候就干过这事,写了个speedup: 0,盯着屏幕看了五分钟,愣是没意识到问题出在倍速上。

还有,如果你手动调用过model.activeAnimations.removeAll()或者animationInstance.stop(),动画对象其实还在,但播放状态已经停了。这种问题在需要频繁切换模型的场景里特别常见。

判断动画是否处于暂停状态,可以看动画实例的state属性,或者直接调用play()重新播放。

3. 一次完整的问题修复过程

3.1 从最小复现开始排查

我当时遇到的情况是这样:用Viewer加载了一个带旋转动画的风扇 glTF,模型正常显示,风扇叶片静止。按照常规思路,我首先怀疑模型问题,于是用 glTF 在线预览确认模型没问题,然后逐项排查加载代码。

先写了一个裸场景:

const viewer = new Cesium.Viewer('cesiumContainer', { shouldAnimate: true }); const model = await Cesium.Model.fromGltfAsync({ url: '/models/fan.glb', modelMatrix: Cesium.Matrix4.fromArray(Cesium.Transforms.eastNorthUpToFixedFrame( Cesium.Cartesian3.fromDegrees(116.39, 39.9, 0) )) }); viewer.scene.primitives.add(model); model.readyEvent.addEventListener(() => { console.log(model.activeAnimations.length); // 输出 1 model.activeAnimations.addAll(); });

结果依然是静止的。控制台输出1,说明动画确实被解析了。那就继续查时钟:

console.log(viewer.clock.shouldAnimate); // false

问题找到了。虽然Viewer创建时设置了shouldAnimate: true,但viewer.clock.shouldAnimate在这个上下文里竟然变成了false——因为之前代码里我手动设置了viewer.clock.shouldAnimate = false,用于暂停时间轴,后来忘了恢复。

看代码看不出问题,查看时钟参数也没发现异常,最后用viewer.clock.tick()单步走了一下才发现时间不走。这一步排查帮助很大。

3.2 逐步定位与修复

修复分三步走:

第一步,恢复时钟:

viewer.clock.shouldAnimate = true; // 或者强制让模型动画不受时钟影响 model.clock = viewer.clock;

第二步,在 ready 之后添加动画:

model.readyEvent.addEventListener(() => { model.activeAnimations.addAll({ speedup: 1.0 }); });

第三步,验证:

viewer.clock.onTick.addEventListener(() => { console.log(viewer.clock.currentTime.toString()); });

修改完后,风扇叶片立刻转动了。

如果你正在用fromGltfAsync但不想等待readyEvent太久,也可以调用model.readyEvent配合Promise.race设置超时。注意不要用setTimeout硬等,因为模型资源加载时长和网络、模型大小强相关,没有固定值。

3.3 针对问题场景的实用调参方法

这里额外说一个选型的方法论。有时候shouldAnimate是 OK 的,但模型动画还是很奇怪,比如位置偏移、循环不闭合。这种问题多数出在quantization上。glTF 文件里的 morph target 动画在导出时往往会被量化压缩,Cesium 对这类数据的支持虽然多数情况可用,但一旦模型复杂,顶点权重精度丢失会导致动画抖动或错位。

遇到这种问题,建议导出时关闭"Quantize"选项,或者使用二进制 glTF(.glb)格式代替 JSON glTF。.glb的文件结构更紧凑,在 Cesium 里解析速度也更快。

我实际测试中发现,同一个模型在用.glb和.gltf两种格式加载时,动画表现完全一样,但.glb加载稳定性更高,极少出现动画不显示的情况。原因可能是.gltf依赖外部的.bin文件,加载顺序或路径问题可能导致模型资源不同步,影响动画初始化。

如果你的动画模型本身很大,比如几十 MB 的回转机械动画,建议优先转.glb并压缩纹理。一个 200MB 的 glTF 在浏览器里光加载就要好几秒,动画不播放的体验会更明显。

4. 常见问题排查速查表与避坑清单

4.1 常见问题速查

现象常见原因排查方法解决方案
动画模型加载后完全不动viewer.clock.shouldAnimate为 false控制台打印viewer.clock.shouldAnimate设置shouldAnimate: true
ready 后activeAnimations.length为 0模型导出没带动画,或加载时序未就绪检查 glTF 里的animations字段重新在 Blender 导出并勾选动画选项
animate 但只播一次animationTimeMode设置成了ABSOLUTE且time不正确检查animationInstance.time的值改成RELATIVE,或设正确的time
动画播放速度异常(极快或极慢)multiplier或speedup设置不当打印动画实例的multiplier设置为 1
动画加载时就报错glTF 资源路径错误或 shader 编译失败看浏览器 NetWork 面板修正 URL 路径或转换 glb 单文件
动画能看到第一个关键帧,但之后不动model.clock未同步到 viewer 的时钟打印model.clock.equals(viewer.clock)手动赋值model.clock = viewer.clock
独立Scene场景下动画不播放没有时钟驱动检查是否有Clock实例创建Clock并设置shouldAnimate

4.2 几个值得养成的调试习惯

第一个习惯是尽量用readyEvent而不是readyPromise配合await。readyEvent触发的时候,模型内部的动画资源已经被解析完毕,这点经过我多次抗压测试,是一个稳妥的操作时机。如果用了readyPromise,在await之后虽然也已经 ready 了,但代码可读性差一些,而且嵌套多了很容易把时序搞乱。

第二个习惯是在动画不播放时,先确认模型本身有没有动画数据。我见过一个客户盯着代码调夯了半天,最后发现模型根本只是静态网格没有任何 AnimationClip,白忙活一场。快速验证的方法是把它丢进 Babylon 沙盒或 Three.js 编辑器里,如果那边也不播,就不要再怀疑 Cesium。

第三个习惯是用viewer.clock.onTick来观察时间轴是否在走。这个方法特别直观,几乎一行代码就能看出问题。凡是动画不动的场景,先看这个事件是否持续触发,如果压根不触发,说明整个时钟系统都在罢工,根本不用管动画相关代码。

第四个习惯是用浏览器 DevTools 的 Performance 面板检查fromGltfAsync加载耗时。如果加载过程阻塞太久,动画系统可能因为同步问题而跳帧或停止。此时需要把加载和动画初始化拆成两个异步阶段,先加载资源,再初始化动画。

4.3 一个隐蔽的高阶配置

Model对象在初始化时有个model.clock,还有一个model.time。很多人被这两个属性搞混淆,但其实它们的职责完全不同。

  • model.clock:只负责决定动画系统是否 tick(即是否推进时间)。
  • model.time:当前模型的仿真时间戳,受model.clock驱动,会持续更新。

我之前为了让动画播放,想着"手动改model.time让它前进",结果发现无论怎么改,动画都不动。后来才反应过来,手动改time只是"跳帧",并没有触发动画系统的更新循环。正确做法是设置model.clock.shouldAnimate = true并让时钟 tick。

如果你需要延迟播放动画(比如等模型转起来角度合适后再让动画开始),可以先model.activeAnimations.addAll(),拿到animation对象,然后调用animation.pause(),等到时机合适再animation.play()。这样比控制clock.shouldAnimate更精准,也不会影响其他模型动画。

4.4 模型动画导出的几个实际建议

作为收尾,讲一下导出端的经验,这部分看似无关,但排查中经常用到。

如果你用 Blender 导出给 Cesium 用的动画模型,记住这几个要点:

  • 导出前选中骨骼和模型,确保动画 Action 已分配给当前对象。
  • 导出时选择 glTF 2.0 格式,勾选"Animation"(新版本叫"Animations")。
  • 不要勾选"Limit to Selected",除非你明确知道自己在做什么,否则骨骼可能不带动画数据。
  • 如果你导出的是带动画的模型,而 Blender 有一套独立的动作状态机(NLA Editor),最好先Push Down一个 action 到 NLA track,不然导出时可能认为没有动画。

我用这个方法帮别人修复过一个案例:Blender 里预览动画正常,但导出 glTF 后动画丢失。原因就是动画 Action 没有正确处理到 NLA 编辑器,导出的文件中根本没有 animation 字段。

关于fromGltfAsync加载带动画的模型时动画无法播放的问题,我自己的体会是:Cesium 模型动画的核心在于时钟,而非模型本身。很多开发者在排查时先怀疑模型、再怀疑 Cesium 的版本兼容性,其实大部分情况下只要盯住clock和readyEvent这两个点,问题就能解决。希望这篇记录能帮大家快速定位到问题,少走弯路。

相关新闻

文献综述智能生成全流程实战:从检索式到初稿的AI辅助指南

文献综述智能生成全流程实战:从检索式到初稿的AI辅助指南

写文献综述写到想摔电脑的人,估计不止我一个。我见过不少同学,实验做得有模有样,最后卡在论文绪论的“国内外研究现状”上,参考文献下载了两三百篇,打开文档却一句话都憋不出来。这种痛苦我太熟悉了。这几年&#xff0…

2026/10/20 23:19:50 阅读更多 →
PPT-Master:技术文档可视化与高效沟通的方法论

PPT-Master:技术文档可视化与高效沟通的方法论

1. “ppt-master”不是软件,而是一类人的隐性能力标签最近在几个技术社区和设计协作群聊里,频繁看到有人发“求个ppt-master带飞”“有没有靠谱的ppt-master接单”“这个需求找ppt-master比找前端还快”。起初我以为是某个新出的AI插件或SaaS工具&#x…

2026/10/20 23:19:50 阅读更多 →
采样终结,演绎之始:虚拟乐器 Instrument X 深度体验

采样终结,演绎之始:虚拟乐器 Instrument X 深度体验

在虚拟乐器圈子里泡久了,你会养成一种本能:听任何一首歌,先猜里面用的是什么音色,是采样库还是合成器,是预制的“万金油”钢琴还是真的为这个编曲调过力度层的音源。最近我拿到的这套名为 Instrument X 的软件&#xf…

2026/10/20 23:19:50 阅读更多 →

最新新闻

BiLSTM-CRF命名实体识别:可解释、轻量、高确定性的NER基线实现

BiLSTM-CRF命名实体识别:可解释、轻量、高确定性的NER基线实现

简介:本资源是一套面向NLP初学者与医疗领域AI开发者的命名实体识别(NER)实战项目,聚焦BiLSTM-CRF模型在临床文本中的实体抽取任务,解决病症、药物、操作等关键信息自动识别难题。资源共24个文件,涵盖5个核心…

2026/10/21 0:08:18 阅读更多 →
GPS定位解算MATLAB仿真:从伪距模型到最小二乘实现

GPS定位解算MATLAB仿真:从伪距模型到最小二乘实现

简介:这是一份基于MATLAB的GPS定位算法仿真程序包,面向导航、测绘、车辆工程与航空航天等领域的学生和研发工程师,用于学习GPS信号模拟、伪距与载波相位测量、最小二乘定位解算以及误差分析等完整链路。压缩包共129个文件,大小2.4…

2026/10/21 0:08:18 阅读更多 →
基于Python的AI学习平台源码:Flask+Celery沙箱评测部署实战

基于Python的AI学习平台源码:Flask+Celery沙箱评测部署实战

简介:这是一份以Python为核心的AI学习平台完整设计源码,面向Python/AI初学者、在线教育平台开发者及教学资源整理者,可用于快速搭建功能全面的编程学习站点。压缩包共1857个文件,约48.55MB,涵盖源码、文档与丰富的静态…

2026/10/21 0:08:18 阅读更多 →
Linux下CMake官方二进制包安装与多目录工程验证

Linux下CMake官方二进制包安装与多目录工程验证

简介:本资源《CMake实战.pdf》是一份面向C/C中高级开发者、跨平台项目构建工程师及开源项目维护者的系统性入门与进阶指南,聚焦解决多操作系统环境下构建流程复杂、依赖管理困难、大型项目配置低效等核心痛点。全书以实战驱动,覆盖CMake安装配…

2026/10/21 0:08:18 阅读更多 →
Java设计模式实战:从面向对象到23种模式的核心解析

Java设计模式实战:从面向对象到23种模式的核心解析

1. 先别急着背模式,搞清楚它们到底在解决什么问题1.1 设计模式不是什么高深的东西我第一次接触设计模式的时候,是在某次项目重构的会议上。那时候一个订单模块的代码堆了两千多行,一个类里既有创建订单的逻辑、又有折扣计算的逻辑、还有状态流…

2026/10/21 0:07:16 阅读更多 →
对话管理系统设计与优化:从状态管理到流式架构的工程实践

对话管理系统设计与优化:从状态管理到流式架构的工程实践

1. 对话管理系统的核心定位:从聊天框到业务中枢做AI原生应用,最难的不是把大模型接口调通,而是设计好那个“看不见的中间层”——对话管理系统。很多团队一开始都会低估这个模块的分量。以为无非是前端收集用户说的话,拼一个Promp…

2026/10/21 0:07:16 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →