对单调的画布说拜拜👋🏻

开始前在这里贴一下我们的项目地址和官网,欢迎大家访问和star⭐️~

项目地址:github.com/didi/LogicF...

官网地址:logicflow.cn/

前言

众所周知,LogicFlow是基于SVG实现的画布,由于没有特别设计过,画布主题默认是这样的👇🏻

虽然现在功能够用,但视觉上确实逐渐跟不上潮流了。

更关键的是,如果你想自定义一套风格统一的画布主题,至少需要经过 4 步操作,涉及多个 API,配置繁琐且易出错:

「修改元素样式 -> 设置画布背景 -> 配置网格 -> 重写边箭头方法调整边箭头样式 -> 其他改动点」

🙋:那有没有通过一套配置完成整个画布主题的配置的办法?

👨🏻:有的,朋友,有的

做了什么

为了能带来更美观的画布、让用户能更方便地配置自定义主题,从2.0.14版本开始LogicFlow对主题模块做了全面升级,让开发者能更便捷地调整主题。具体包括三个方面:

  1. 新增3套内置主题,满足多种审美风格
  2. 主题配置能力增强:支持多边形圆角、箭头样式、背景和网格统一设置
  3. 支持用户配置自定义主题,一行代码切换画布主题

这里主要为大家分享一下这次优化的实现思路,以供有需要的朋友参考。

如何实现

LogicFlow 的主题模块本质是对画布各元素样式的统一配置。当前支持配置的元素与属性如下:

目前我们对外提供了两种配置主题的方式:

  • 初始化配置中传入 style 参数

当创建 LogicFlow 实例时,传入的 style 会被构造函数读取并传给 GraphModel。GraphModel 在初始化时会调用 setupTheme 方法,将传入的 style 与默认主题合并后,存入 theme 字段中。

在画布渲染阶段,视图组件会从各自的 model 中读取 graphModel.theme,并将样式应用到对应的 SVG 元素上,完成样式展示。

  • 运行时调用 setTheme() 方法

调用 setTheme 方法时,LogicFlow 会触发 GraphModel 的 setTheme 方法,将当前主题与传入的样式合并后再次调用 setupTheme,生成更新后的主题并存入 theme 字段。

得益于内部使用的 MobX 响应式机制,theme 的变更会自动触发视图层的更新,使样式即时生效。

实现步骤

Step 1 新增主题映射与切换方法

新增主题映射非常简单,只需参考现有的配置结构,新增三套主题样式并加入映射表即可。

接着为 setTheme 方法新增一个控制主题字段的可选参数 themeMode:

当调用 setTheme(theme, themeMode) 时,内部流程如下:

  1. 优先根据传入的 themeMode 查找对应的预设主题;
  2. 将预设主题与当前基础样式合并;
  3. 如果还传入了 theme(即自定义样式),则继续合并;
  4. 最终生成的主题配置会更新到 theme 中并回显至视图。

这样就实现了预设主题 + 自定义主题的灵活组合。

Step 2 样式合并机制

引入主题模式后,我们需要处理三类样式来源:

  • 基础样式(LogicFlow 内置默认样式)
  • 主题样式(通过 themeMode 引入的预设样式)
  • 自定义样式(用户通过 style 或 setTheme 设置)

这也引出了一个关键问题:

「样式的优先级该如何处理?如何确保高优先级的样式不被覆盖?」

在引入主题模式之前,样式优先级是这样的:

setTheme 设置的样式 > 初始化时通过 style 设置的样式 > 内置基础样式

但在支持主题模式后,如果不做处理,任何一次 setTheme 的调用都会导致之前的样式被完全覆盖,无论是主题样式还是用户定制样式。

为了解决这个问题,我们明确了新的样式优先级:

setTheme 的自定义样式 > style 设置的自定义样式 > 主题样式 > 基础样式

为了实现这一机制,我们新增了一个 customStyle 字段,专门用来存储用户的自定义样式:

  • 初始化时,customStyle 会保存用户传入的 style;
  • 每次调用 setTheme 时,会将传入的自定义样式与已有的 customStyle 合并,再与主题样式及基础样式合并生成最终的 theme;
  • 合并后的 customStyle 会重新存储,等待下一次更新。

通过这样的机制,我们实现了主题样式与用户样式的隔离,保证用户配置的高优先级样式在切换主题时依然生效、不会被覆盖。

Step 3 构建自定义主题

在支持内置主题切换的基础上,我们还希望给用户更多自由 ------ 能否定义属于自己的主题? 为此,我们新增了 LogicFlow.addThemeMode 静态方法,允许用户注册自定义主题。

该方法接受两个参数:

  • themeMode:主题名称
  • config:该主题的样式配置对象

用户只需调用 LogicFlow.addThemeMode('myTheme', customThemeConfig); 即可将自定义主题注册进框架,并像使用内置主题一样通过 setTheme 切换。

内存管理

需要注意的是:不论是内置的 4 套主题,还是用户注册的自定义主题,都是通过静态方式全局存储的。

这意味着这些配置在页面生命周期内会一直存在内存中。

为避免潜在的内存泄漏问题,我们还提供了两个辅助方法:

  • LogicFlow.removeThemeMode(themeMode):移除指定主题
  • LogicFlow.clearThemeMode():清空所有注册的自定义主题

通过这两个方法,用户可以按需清理主题配置,确保资源使用更可控。

Step 4 细节增强

圆角多边形

在 SVG 中,像矩形这样的图形可以直接通过 radius 设置圆角,但 多边形(如菱形、五边形)原生并不支持圆角配置。为了让所有几何图形在视觉风格上保持一致,我们对多边形进行了封装,支持圆角渲染。

实现思路简述如下:

  1. 遍历多边形的所有顶点;
  2. 对每个顶点,使用前后点形成的向量计算圆角的起点和终点;
  3. 使用路径命令画出从前一点到圆角起点的直线;
  4. 再以当前顶点为控制点、起终点为端点绘制二次贝塞尔曲线,形成圆角;
  5. 依次处理所有顶点,最终形成带圆角的平滑多边形路径。

箭头样式配置化

默认情况下,LogicFlow 边的箭头样式为实心箭头。如果想换成其他形态(如线条箭头或菱形箭头),此前需要用户手动重写逻辑,门槛较高。

为简化这一过程,我们新增了以下三种内置箭头样式,并提供了 startArrowType 和 endArrowType 两个主题配置项,一行配置即可定制起终点箭头样式。

  • 线条箭头
  • 圆形箭头
  • 菱形箭头

这些箭头本质上都是 SVG 路径,遵循相同的绘制逻辑,支持如下参数:

  • offset:箭头长度
  • verticalLength:箭头高度
  • refX/refY:箭头参考点位置,影响箭头在边上的相对位置

此外,我们还引入了两个 SVG 样式相关配置:

  • strokeLinecap:定义线段的端点样式,效果与SVG stroke-linecap 属性相同(如 round、square)
  • strokeLinejoin:定义线段连接处的样式,效果与SVG stroke-linejoin 属性相同(如 bevel、round)

通过它们可以进一步提升箭头在不同背景和缩放下的视觉表现。

背景、网格统一配置

在 2.0.14 之前,用户配置画布背景和网格时,必须通过专门的 API:

  • background、grid 初始化参数
  • updateBackgroundOption() / updateGridOptions() 方法

这对主题统一配置带来了不便。

为了解决这一问题,我们在新版本中支持通过 style 和 setTheme 配置背景与网格,将其纳入主题体系中。

配置方式保持不变,原有的 background 和 grid 参数依然生效;新的方式只是提供了一种更便捷的统一配置路径。

注意优先级差异:

初始化阶段,background/grid 参数的优先级高于 style 中的同类配置;

运行时阶段,setTheme、updateBackgroundOption 和 updateGridOptions 优先级等同。

总结:如何为SVG画布及其元素增加主题?

在构建流程图编辑器时,我们常常希望画布及其图形元素能根据不同的主题(如浅色、深色等)进行风格切换,同时又允许用户自定义细节样式。为了实现可维护、可扩展的主题系统,或许可以参考LogicFlow这样的一套通用解决方案:

  • 统一配置边界: 尽量将所有可视属性统一纳入主题样式的管理范围内;
  • 设计统一的样式注入机制: 内部维护一个样式模型,并设计样式作用到元素的生效链路,将主题样式以对象形式注入到画布及其子元素的样式计算中;
  • 构建样式合并规则: 根据实际的样式来源和更新时机,约定一个固定的合并样式规则,必要的情况下可以把不同优先级的样式分开存储,方便组合;
  • 提供用户自定义配置的能力: 提供统一的API/参数,支持用户根据自己的诉求灵活调整主题和样式;

如果这篇文章对你有帮助,欢迎关注我们的账号,我们会持续输出干货文章。也希望您能为我们的项目点上 Star,这对我们非常重要,感恩的心~

项目地址传送门:github.com/didi/LogicF...

相关推荐
AI 菌23 分钟前
文心一言大模型4.5系列开源测评
开源·文心一言
寻觅~流光1 小时前
封装---统一封装处理页面标题
开发语言·前端·javascript·vue.js·typescript·前端框架·vue
恰薯条的屑海鸥2 小时前
前端进阶之路-从传统前端到VUE-JS(第五期-路由应用)
前端·javascript·vue.js·学习·前端框架
三花AI2 小时前
kimi 又好起来了!月之暗面开源 Kimi K2:320 亿参数 MoE 模型登顶 HF 榜首
开源
我是一只代码狗3 小时前
idea中使用git
git·gitee·github
武子康5 小时前
AI炼丹日志-30-新发布【1T 万亿】参数量大模型!Kimi‑K2开源大模型解读与实践
人工智能·gpt·ai·语言模型·chatgpt·架构·开源
产品经理独孤虾5 小时前
GitHub Copilot:产品经理提升工作效率的AI助手
github·copilot·产品经理·原型设计·ai工具·效率提升·prd
编程乐趣5 小时前
库存订单管理系统:3月份开源项目汇总
开源
杜莱6 小时前
IDEA 安装AI代码助手GitHub Copilot和简单使用体验
人工智能·github·intellij-idea