ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PlantUML 交互式 SVG 指南:用 `svginteractive` 让类图与时序图“活“起来

PlantUML 交互式 SVG 指南:用 `svginteractive` 让类图与时序图“活“起来 开发工具文档【免费下载链接】plantumlGenerate diagrams from textual description项目地址https://gitcode.com/gh_mirrors/pl/plantuml点击查看免费下载PlantUML 通过!pragma svginteractive true即可把交互脚本与样式直接嵌入生成的svg中让类图支持悬停/点击高亮、让时序图支持吸顶表头与参与者过滤。本文以仓库内 src/main/resources/svg/README.md 为主线结合默认与时序图两套脚本/样式的源码实现、嵌入机制和回归测试讲解如何启用、各交互行为背后的原理以及如何自定义这些前端资源。读完你既能快速上手交互式 SVG也能理解其事件绑定、CSS 状态机、data-*数据承载的实现套路为二次定制打下基础。一、启用方式一个 pragma 开关交互式 SVG 由 PlantUML 渲染管线在输出 SVG 时按需开启。只需要在.puml源文件顶部写入startuml !pragma svginteractive true ... enduml开启后PlantUML 会把两套资源内嵌进生成的 SVGsequencediagram.*—— 仅用于时序图sequence diagramdefault.*—— 用于其余所有图型包括类图、对象图、组件图等。仓库内的回归测试直接印证了这一点。在 InteractiveSvgMinifiedAssetsTest.java 中时序图用例alice - bob: hello断言内嵌内容包含sequencediagram.js与sequencediagram.css类图用例class A、class B、A -- B则断言指向default.js与default.css见 InteractiveSvgMinifiedAssetsTest.java。此外测试资源目录 src/test/resources/vega/svg/interactive 下的SVG0004_Svek.puml、SVG0005_Svek.puml、SVG0006_Svek.puml以及非回归用例 src/test/resources/vega/nonreg/svg/SVG0002.puml8 种参与者类型齐全的时序图都以!pragma svginteractive true开头用于验证交互 SVG 在类图与时序图两类渲染路径上的稳定性。二、资源文件组织源码可读产物精简交互资源共 8 个文件全部位于 src/main/resources/svg文件作用default.js/default.css非时序图类图等交互逻辑与样式的可读源码default.min.js/default.min.css内嵌进 SVG 的压缩版类图sequencediagram.js/sequencediagram.css时序图交互逻辑与样式的可读源码sequencediagram.min.js/sequencediagram.min.css内嵌进 SVG 的压缩版时序图官方维护约定非常明确见 README优先编辑未压缩的源码default.js、default.css、sequencediagram.js、sequencediagram.css改完后再重新生成对应的.min.*文件压缩 JavaScript 可用 terserCSS 做一次空白字符清理即可每个压缩文件的开头都保留一段短注释指回其未压缩源码在 GitHub 上的位置。例如default.min.js第一行就是/* Source (unminified): https://github.com/plantuml/plantuml/blob/master/src/main/resources/svg/default.js */见 default.min.js。之所以坚持内嵌压缩版是为了控制 SVG 文件体积。这一点被测试明确守护InteractiveSvgMinifiedAssetsTest会断言embeddedPayloadSize unminifiedPayloadSize即嵌入的style与script总字节数必须小于未压缩源码见 InteractiveSvgMinifiedAssetsTest.java同时断言压缩版中没有function toggleFloatingHeader()、function escapeForCssAttributeSelector这类美化排版痕迹防止把未压缩源码整体塞进 SVG同文件 L46-L47、L74-L75。嵌入机制在源码中的落点从源码结构看交互资源的读取与内嵌发生在 SVG 图形绘制层 SvgGraphics.javagetStylesForInteractiveMode()读取option.getInteractiveBaseFilename() .min.css包成style typetext/css的 CDATA 节点SvgGraphics.javagetScriptForInteractiveMode()读取同名的.min.js写入script节点SvgGraphics.java两者通过getData(name)从类路径/svg/下加载资源SvgGraphics.java。资源文件名本身由 SvgOption.java 中的interactiveBaseFilename字段决定withInteractive(...)写入该值SvgOption.javaisInteractive()以它为null与否判断是否开启交互模式SvgOption.java。也就是说用哪一套脚本完全由渲染时传入的 base 文件名决定default与sequencediagram只是两个不同命名的资源包。三、类图default 资源交互特性default.*为类图等实体关系型图提供聚焦高亮交互README 描述的核心行为有三条源码中均有对应实现。3.1 悬停高亮鼠标悬停到某个实体上时图中大部分元素被调暗只有该实体以及与之直接相连的实体和连线保持高亮移开后恢复原样。实现上default.js为每个g.entity注册了mouseover/mouseout事件见 default.jsentity.addEventListener(mouseover, onMouseOverEntity); entity.addEventListener(mouseout, onMouseOutEntity);onMouseOverEntity调用handleSelectNeighbors(this, mouseover)default.js其核心逻辑是清理之前残留的mouseover-selected/mouseover-highlighted类给根svg加mouseover-active类通过getEdgesAndDistance1Nodes找到与当前实体距离为 1 的所有节点和连线打上mouseover-highlighteddefault.js、default.js。CSS 侧的分层逻辑见 default.csssvg.mouseover-active g * { opacity: 0.2 !important; /* 非高亮元素调暗 */ } svg.mouseover-active g g.mouseover-highlighted { opacity: 1.0 !important; /* 高亮元素保持全亮 */ }只影响直连邻居由getEdgesAndDistance1Nodes保证它通过svg.querySelectorAll(.link[data-entity-1...], .link[data-entity-2...])精确找出包含当前节点名存于节点id中的所有连线再把连线的另一端点一并加入高亮集合。3.2 点击锁定高亮单击实体后高亮持续保留鼠标移开也不会消失再次点击同一实体或按下Esc键即可取消。对应实现单击事件onClickEntity若该实体已被click-selected且 SVG 处于click-active则执行handleDeselect(click)否则调用handleSelectNeighbors(this, click)default.jsEsc键处理SVG 根元素上监听keydown命中Escape即handleDeselect(click)default.js点击态样式由 default.css 提供规则与悬停态同构click-active/click-highlighted只是调暗系数略有不同0.3vs0.2。3.3 悬停优先于点击当点击锁定与悬停同时发生时悬停产生的高亮优先README 明确这一优先级。原因在于两个事件共用-active/-selected/-highlighted三组类前缀不同互不干扰悬停态以mouseover-*类驱动CSS 用!important保证显隐点击态以click-*类驱动两者是叠加而非互斥视觉上悬停态始终盖过点击态。3.4 源码中的额外能力双击整链高亮README 未提及但源码明确实现了另一交互dblclick双击实体时会调用handleSelectLine高亮整条关系链default.js。与单击的距离 1 邻居不同getLineEdgesAndNodes通过递归向前驱和后继两个方向遍历所有关联连线与节点default.js实现沿连线全链路的传递高亮。需要精确交互行为的读者可直接参考这段递归实现。四、时序图sequencediagram 资源交互特性sequencediagram.*为时序图提供两类交互均由 sequencediagram.js 在DOMContentLoaded后初始化sequencediagram.js。4.1 吸顶浮动脉冲表头README 描述鼠标移到时序图顶部的参与者表头区域时左上角会浮现一个 pin图钉按钮点击后表头可随页面滚动而保持可见吸顶。源码实现分四步聚合表头groupParticipantHeaders()把所有g.participant-head移入一个新的g classheader并追加一个背景rect作为命中区域sequencediagram.js创建图钉按钮createFloatingHeaderToggleButton生成一个含title、背景矩形和别针图标的g classfloating-header-toggle-buttonsequencediagram.js克隆浮动表头createFloatingHeader深拷贝原始表头并标记floating-headerupdateFloatingHeaderPosition依据页面/祖先容器溢出量计算translate(0, overflow)位移实现吸顶sequencediagram.js滚动监听同时监听window的scroll与所有可滚动祖先容器的scrollisScrollableContainer判断overflowY为auto/scroll且存在溢出保证在任意滚动容器内都生效sequencediagram.js。值得注意的细节图钉开关状态会持久化到window.localStorage的net.sourceforge.plantuml.sequence-diagram.floating-header.active键sequencediagram.js页面刷新后仍保持上次选择同时脚本对初始化/滚动/切换过程中的异常做了try/catch降级——出错时移除floating-header-active并打上floating-header-error类避免交互脚本破坏整个 SVGsequencediagram.js。按钮显隐与淡出动画在 sequencediagram.css 中定义默认opacity: 0且visibility: hidden表头悬停时显示带 2 秒后淡出的fadeOut动画按钮自身悬停时保持全显并取消动画sequencediagram.css。所有规则都以svg[data-diagram-typeSEQUENCE]为前缀避免污染同页面其他 SVG。4.2 参与者过滤源码中的隐藏能力README 未写、但sequencediagram.js明确实现的另一功能点击参与者头部即可过滤高亮。handleParticipantFilterClick以data-participant属性记录每个被选参与者的名字仅选中 1 个参与者时所有与该参与者有关的g.message均高亮participant1Matches || participant2Matches选中多个时只有两端都被选中的消息高亮且排除自环participant1 ! participant2选中集合为空时移除filter-active状态有选中但无匹配消息时打上filter-nomatch类sequencediagram.js。过滤的高亮样式由 CSS 动态注入的colorize-green/colorize-red两个feColorMatrix滤镜实现绿有匹配红无匹配见 sequencediagram.js 与 sequencediagram.css。时序图用例 SVG0002.puml 覆盖了 8 种参与者类型actor、boundary、collections、control、database、entity、participant、queue可视为该功能的测试场景。五、实现细节与设计约束5.1 多 SVG 共存document.currentScript定位自身由于交互脚本以script内嵌在各自 SVG 内多个交互 SVG 同处一个 HTML 页面时脚本必须只作用于自己所在的那个svg。实现方式是在脚本顶部立即执行const svg findAncestorWithTagName(document.currentScript, svg);即沿着document.currentScript向上查找最近的svg祖先default.js、sequencediagram.js。README 特别提醒document.currentScript在回调或事件处理器内部不可用因此这一查找必须在脚本顶层同步完成事件处理一律基于已捕获的svg变量闭包引用。CSS 侧同样用作用域前缀如svg[data-diagram-typeSEQUENCE]约束样式只作用于对应 SVG。5.2 用户自定义标识符用data-*而非classREADME 明确的设计决策不把用户自定义的实体/参与者名称放进class属性。原因很实际——名称my entity会被拆成my和entity两个类.、:、,、[等字符在 CSS 选择器中都要小心转义。取而代之的方案用户名称存放在data-entity-1、data-entity-2连线两端、data-participant参与者等data-*属性中生成 XML 时只需常规 XML 转义如→quot;只有在把这些值用于 CSS 属性选择器时才需要额外转义和\由escapeForCssAttributeSelector统一处理function escapeForCssAttributeSelector(entityName) { return entityName ?.replaceAll(\\, \\\\) ?.replaceAll(, \\); }见 default.js。这一设计的健壮性由专门的测试资源背书SVG0004_Svek.puml 中的类名包含了换行、制表符、几乎全部 ASCII 特殊字符以及大量 Unicode 符号!#$%()*,-/:;?[]^_{|}~、¡™£€∞§¶•ªºæ≤≥π¥ƒ©ç®¬÷≠åø´¨ˆ∂˙†˜ß«œ∆˚≈♭µ∑√Ωìñ☕️ 等用来验证任意用户名称都不应破坏选择器或高亮逻辑。六、快速上手与验证要在本地体验交互式 SVG编写带!pragma svginteractive true的.puml文件参考上述任一测试用例的写法使用 PlantUML 的 SVG 输出例如命令行java -jar plantuml.jar -tsvg your-diagram.puml或通过任意支持FileFormat.SVG的 APISourceStringReader.outputImage(..., new FileFormatOption(FileFormat.SVG))见 InteractiveSvgMinifiedAssetsTest.java用浏览器打开生成的 SVG即可测试类图悬停/单击/双击/Esc以及时序图的图钉吸顶与参与者过滤。七、自定义交互资源的建议若需调整交互行为或样式遵循仓库的维护约定只改未压缩源码编辑 default.js、default.css、sequencediagram.js、sequencediagram.css重新生成压缩版JavaScript 用 terser保留首行源码链接注释CSS 做空白清理压缩产物仍须以Source (unminified):注释指回源码路径保持资源名不变SvgGraphics按{base}.min.css/{base}.min.js从类路径/svg/加载SvgGraphics.java改名会导致嵌入失败回归验证提交后运行InteractiveSvgMinifiedAssetsTest断言脚本/样式存在、源码链接注释存在、嵌入体积小于未压缩源码并确保 src/test/resources/vega/svg/interactive 下的交互用例继续通过。结语交互式 SVG 是 PlantUML 输出能力中小而精的一环一个 pragma 开关、两套各四份前端资源就为类图与时序图赋予了浏览器端的动态交互。理解其未压缩源码维护 压缩产物嵌入 测试守护体积与钩子的工作流以及document.currentScript作用域定位与data-*承载用户标识符两个关键设计既能让你熟练使用也能让你安全地按需定制属于自己的交互 SVG。赞分享开发工具文档【免费下载链接】plantumlGenerate diagrams from textual description项目地址https://gitcode.com/gh_mirrors/pl/plantuml点击查看免费下载相关推荐Blazored.Modal高级配置掌握模态框动画、定位与尺寸控制Blazored.Modal高级配置掌握模态框动画、定位与尺寸控制 想要为你的Blazor应用程序打造专业级的用户体验吗Blazored.Modal高级配置前端UI组件3分钟上手twin.macro让SVG图标活起来的样式魔法3分钟上手twin.macro让SVG图标活起来的样式魔法 你是否还在为SVG图标样式调整繁琐而头疼既要写冗长的CSS又要处理各种交互状态twin.ma前端开发工具mini3d深度缓存原理如何实现3D场景的可见性判断mini3d深度缓存原理如何实现3D场景的可见性判断 mini3d是一个仅用700行代码实现的3D软件渲染器其核心功能之一就是通过深度缓存Z buffer图形学文档/教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表