Files
yys-editor/docs/2design/StyleAndAppearance.md

115 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 样式与节点结构说明v1
## 背景
- 目标:统一节点的样式字段与渲染消费路径,避免各节点分散管理填充/描边/阴影/文字等样式。
- 数据载体:沿用 LogicFlow 的 `GraphData`,仅约定 `node.properties` 内的业务字段与样式字段。
## 样式模型:`properties.style`
位于每个节点 `properties.style`,是尺寸与外观的单一事实来源;渲染时会同步 `style.width/height` 到节点的 `width/height`
```ts
interface NodeStyle {
// 尺寸与变换
width: number; // px必填
height: number; // px必填
rotate?: number; // deg逆时针围绕节点中心
// 形状
fill?: string; // 背景填充色
stroke?: string; // 描边色
strokeWidth?: number; // ≥0px
radius?: number | [number, number, number, number]; // 圆角rect 生效)
opacity?: number; // 0..1
// 阴影
shadow?: { color?: string; blur?: number; offsetX?: number; offsetY?: number };
// 文本样式text 节点或带文本的节点)
textStyle?: {
color?: string;
fontFamily?: string;
fontSize?: number; // px
fontWeight?: number | string;
lineHeight?: number; // 推荐 1..3
align?: 'left' | 'center' | 'right';
verticalAlign?: 'top' | 'middle' | 'bottom';
letterSpacing?: number; // px
padding?: [number, number, number, number];
background?: string;
};
}
```
默认值参考 `src/ts/schema.ts:DefaultNodeStyle`
- `width=180, height=120, rotate=0`
- `fill='#ffffff', stroke='#dcdfe6', strokeWidth=1, radius=4, opacity=1`
- `shadow={ color:'rgba(0,0,0,0.1)', blur:4, offsetX:0, offsetY:2 }`
- `textStyle={ color:'#303133', fontFamily:'system-ui', fontSize:14, fontWeight:400, lineHeight:1.4, align:'left', verticalAlign:'top', letterSpacing:0, padding:[8,8,8,8] }`
## 归一化与工具(`src/ts/nodeStyle.ts`
- `normalizeNodeStyle(style, sizeFallback)`补全缺省数值钳制opacity ∈[0,1]),将散落的 width/height 收敛到 style。
- `normalizePropertiesWithStyle(props)`:返回带规范化 style 的 props并镜像 `width/height`
- `toContainerStyle` / `toTextStyle`:将 `NodeStyle` 转为 Vue 行内样式(背景、描边、圆角、阴影、透明度 / 文字)。
- `styleEquals`:归一化后比较,避免重复 setProperties。
## 节点元信息:`properties.meta`
```ts
interface NodeMeta {
z?: number; // 层级
locked?: boolean; // 锁定
visible?: boolean; // 可见
groupId?: string; // 分组
name?: string;
createdAt?: number;
updatedAt?: number;
}
```
FlowEditor 在渲染/normalize 时会补齐 `meta.visible=true``meta.locked=false` 并应用到节点模型(可见性、可拖拽等)。
## 监听与渲染路径
1) **归一化入口**`FlowEditor.normalizeNodeModel` 在节点创建/属性变更/渲染后执行:
- 归一化 `properties.style``meta`,必要时回写 `lf.setProperties`
- 同步 `style.width/height` 到节点模型,保证渲染尺寸一致。
2) **事件监听**:节点组件通过 composable 监听 `NODE_PROPERTIES_CHANGE`,实时更新样式与自定义数据。
## 复用方案:`useNodeAppearance``src/ts/useNodeAppearance.ts`
作用:在节点组件中统一获取样式和属性变更。
```ts
const { containerStyle, textStyle } = useNodeAppearance({
onPropsChange(props, node) {
// 可在这里同步业务字段,例如 image url、shikigami 数据等
}
});
```
内部行为:
- 注入 `getNode`/`getGraph`,挂载时读取当前节点 props。
- 监听 `NODE_PROPERTIES_CHANGE`,调用 `normalizeNodeStyle`,输出 `containerStyle`/`textStyle`
- 自动解绑监听,减少重复代码。
已接入的节点组件:
- 图片节点 `src/components/flow/nodes/common/ImageNode.vue`
- 式神节点 `.../yys/ShikigamiSelectNode.vue`
- 御魂节点 `.../yys/YuhunSelectNode.vue`
- 属性节点 `.../yys/PropertySelectNode.vue`
## 编辑入口PropertyPanel
- 样式面板 `src/components/flow/panels/StylePanel.vue` 写入 `properties.style`
- 填充色、描边色/线宽、圆角、阴影(色/模糊/偏移)、透明度
- 文本对齐、行高、字重
- 图片面板 `ImagePanel.vue` 写入宽高/fit/url并保持与 `style.width/height` 同步。
- 其他面板(式神/御魂/属性)仅写业务字段,样式统一由 `useNodeAppearance` 消费。
## 持久化与 schema
- 顶层导出结构:`RootDocument`(见 `docs/2design/DataModel.md`),包含 `schemaVersion`
- 保存/导入路径:`useFilesStore` 写出/读入 `schemaVersion`;缺省数据走 `migrateToV1` 将散落的宽高/可见/锁定补齐到 `properties.style/meta`
## 校验建议
- width/height > 0strokeWidth ≥ 0radius ≥ 0 或四元组合法opacity ∈ [0,1]。
- 文本fontSize > 0lineHeight 合理1~3padding 四元组 ≥ 0。
- 圆角仅对 rect 类节点生效;其他 kind 忽略 radius。
## 后续扩展建议
- 文本节点接入富文本:在 `textStyle` 扩展行高倍数、字间距、背景/描边。
- 叠加高级效果blendMode/filter保持向后兼容新增字段时通过 `schemaVersion` 控制迁移。
- 矢量节点:在 `vector` 节点中消费同一套 `style`,并在编辑面板复用 `StylePanel`